Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

[SOLVED]Why are library functions erasing the contents of registers?

registering

  • Please log in to reply
6 replies to this topic

#1 restin84

restin84

    CC Resident

  • Advanced Member
  • PipPipPipPip
  • 88 posts
  • Programming Language:C, Java, C++
  • Learning:PHP, Python, Assembly

Posted 30 October 2012 - 02:33 PM

I am using a for loop in an ia32 program to get user input to populate an array. It seems that every time I call printf or scanf the contents of the registers get set back to zero. Why is this happening?
  • 0

#2 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts
  • Programming Language:C, Java, C++, PHP, Python, JavaScript, Perl, Assembly, Bash, Others
  • Learning:Objective-C

Posted 30 October 2012 - 03:50 PM

Only certain registers are guaranteed to be preserved across function calls; any function can use the other registers as it likes. The registers that must be preserved are EDI, ESI, EBX, EBP, ESP. The functions you call can use EAX, ECX, and EDX without restoring them. In fact, functions put their return values in EAX.

Note: The list of registers is different for 64-bit systems.
  • 0

sudo rm -rf / && echo $'Sanitize your inputs!'


#3 restin84

restin84

    CC Resident

  • Advanced Member
  • PipPipPipPip
  • 88 posts
  • Programming Language:C, Java, C++
  • Learning:PHP, Python, Assembly

Posted 30 October 2012 - 04:04 PM

So if I need to populate an array I shouldn't use %eax to hold the size of the array. Because if I'm using scanf inside the loop its just going to reset %eax to 0? Is scanf returning 0 because it executed successfully?
  • 0

#4 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts
  • Programming Language:C, Java, C++, PHP, Python, JavaScript, Perl, Assembly, Bash, Others
  • Learning:Objective-C

Posted 30 October 2012 - 04:23 PM

No, in fact if you look at the documentation here, it says that scanf() returns the number of fields stored to. A return value of 0 means that nothing was read.
  • 1

sudo rm -rf / && echo $'Sanitize your inputs!'


#5 restin84

restin84

    CC Resident

  • Advanced Member
  • PipPipPipPip
  • 88 posts
  • Programming Language:C, Java, C++
  • Learning:PHP, Python, Assembly

Posted 30 October 2012 - 04:25 PM

Okay thanks a lot. I need to study my caller save/callee save registers apparently. This is great practice considering I have a midterm on Thursday.
  • 0

#6 restin84

restin84

    CC Resident

  • Advanced Member
  • PipPipPipPip
  • 88 posts
  • Programming Language:C, Java, C++
  • Learning:PHP, Python, Assembly

Posted 30 October 2012 - 05:59 PM

Only certain registers are guaranteed to be preserved across function calls; any function can use the other registers as it likes. The registers that must be preserved are EDI, ESI, EBX, EBP, ESP. The functions you call can use EAX, ECX, and EDX without restoring them. In fact, functions put their return values in EAX.

Note: The list of registers is different for 64-bit systems.


So I have this so far
/************************************************************************/
/************************UNINITIALIZED-GLOBAL-DATA***********************/
    .comm A,100,4        #array A[]
   
/************************************************************************/
/****************************READ-ONLY-DATA******************************/
    .section    .rodata
    .align 4
str1:    .string    "Enter size of array: "
str2:    .string "Enter %d integer elements: "
frmt1:    .string    "%d"

   
teststr1:    .string "n=%d, i=%d"
teststr2:    .string    "n=%d\n"
teststr3:    .string "array size = %d"
teststr4:    .string "element = %d"
eaxcontents:    .string "%eax = %d"
ebxcontents:    .string "%ebx = %d"
contentsofesi:    .string "%esi = %d"
element1input:    .string "enter array element 1"
element2input:    .string "enter array element 2"
element1:    .string "element1 = %d"
element2:    .string "element2 = %d"
/************************************************************************/   
/****************************MAIN-FUNCTION*******************************/
    .text            #text section
.global    main            #declare main as global
main:
    pushl    %ebp        #prolog save old %ebp
    movl    %esp, %ebp    #prolog set new %ebp

    subl    $4, %esp    #create space in memory for local var n

    pushl    $str1        #push string onto stack for user input
    call    printf        #call printf
    addl    $4, %esp    #pop arguments off stack

    lea    -4(%ebp), %ebx  #load address for var n
    pushl    %ebx        #push %ebx holding address for n
    pushl    $frmt1        #push format string onto stack
    call    scanf        #call scanf
    addl    $8, %esp    #pop arguments off stack
    movl    -4(%ebp), %ebx

    pushl    %ebx
    pushl    $str2
    call    printf
    addl    $8, %esp
   
    movl    $0, %esi

    cmpl    %ebx, %esi
    jge    done
loop:    pushl    %edi
    pushl    $frmt1
    call    scanf
    addl    $8, %esp
    incl    %esi
    cmpl    %ebx, %esi
    jl    loop
done:   



    leave            #epilog
    ret            #epilog
 

At the momemt I just want to overwrite register EDI until the loop exits. When I figure out how to get that working I will mov the contents of EDI into the array. However, I'm getting a segmentation fault.
  • 0

#7 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts
  • Programming Language:C, Java, C++, PHP, Python, JavaScript, Perl, Assembly, Bash, Others
  • Learning:Objective-C

Posted 30 October 2012 - 08:25 PM

You have to save EBX before you use it and restore it just before returning, even in main(). Remember, the operating system calls main() and it's expecting it to follow the rules.
  • 0

sudo rm -rf / && echo $'Sanitize your inputs!'






Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download