Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

[SOLVED]Should I place local variables in registers before performing operations?

registering

  • Please log in to reply
9 replies to this topic

#1 restin84

restin84

    CC Resident

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

Posted 01 November 2012 - 05:23 PM

If I am using a local variables to control a for loop, is it better to place these values into registers before doing comparisons between OR incrementing them?
  • 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 01 November 2012 - 05:26 PM

If they're used frequently, then yes; otherwise, don't worry too much about it. What do you mean specifically? Can you show us some code?
  • 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 01 November 2012 - 05:32 PM

Well I don't have much yet. But I'm trying to avoid making too much mess. I'm new to assembly and I'm learning that it can get messy quickly. I have noticed that certain instructions such as cmpl don't take two memory instructions.
  • 0

#4 restin84

restin84

    CC Resident

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

Posted 01 November 2012 - 05:52 PM

If they're used frequently, then yes; otherwise, don't worry too much about it. What do you mean specifically? Can you show us some code?

Okay I have this. Just sequentially printing elements of an array. I don't know if maybe I can make it cleaner?/more efficient?
.data
    .align 4
A:    .long 1,2,3,4,5

    .section .rodata
str:    .string "A[%d] = %d"
ebxcontents:    .string "ebx = %d \n"
eaxcontents:    .string "eax = %d\n"
    .text
.global main
main:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    $5, -4(%ebp)    #n = 5
    movl    $0, -8(%ebp)    #i = 0

    
    movl    -4(%ebp), %eax    #%eax = n
    movl    -8(%ebp), %ebx  #%ebx = i
    cmpl    %eax, %ebx
    jge    done
loop:    pushl    A(,%ebx,4)
    pushl    %ebx
    pushl    $str
    call    printf
    addl    $12, %esp
    incl    -8(%ebp)
    movl    -4(%ebp), %eax    #%eax = n
    movl    -8(%ebp), %ebx  #%ebx = i
    cmpl    %eax, %ebx
    jl    loop    
done:    
    


    leave
    ret


  • 0

#5 dargueta

dargueta

    I chown trolls.

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

Posted 01 November 2012 - 06:02 PM

1) loop is an instruction, don't use it as a label name. Pick something else.

2) You can't use EBX like that. According to conventions you have to save EBX, ESI, EDI, and EBP before using them in your function, and you must restore their values before returning. You can freely use EAX, EDX, and ECX. You can't expect these registers to have the same values after you call a function.

As for efficiency, I'd fix these things first and then try optimizing it.
  • 0

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


#6 restin84

restin84

    CC Resident

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

Posted 01 November 2012 - 07:39 PM

1) loop is an instruction, don't use it as a label name. Pick something else.

2) You can't use EBX like that. According to conventions you have to save EBX, ESI, EDI, and EBP before using them in your function, and you must restore their values before returning. You can freely use EAX, EDX, and ECX. You can't expect these registers to have the same values after you call a function.

As for efficiency, I'd fix these things first and then try optimizing it.

So I changed the label name for my loop and I used register EAX in place of register EBX. Do you have any code snippits of saving/restoring registers EBX,ESI, EDI, EBP? I can't seam to find any illustrations of this.
    .data
    .align 4
A:    .long 1,2,3,4,5

    .section .rodata
str:    .string "A[%d] = %d"
ebxcontents:    .string "ecx = %d \n"
eaxcontents:    .string "eax = %d\n"
    .text
.global main
main:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    $5, -4(%ebp)    #n = 5
    movl    $0, -8(%ebp)    #i = 0

    
    movl    -4(%ebp), %eax    #%eax = n
    movl    -8(%ebp), %ecx  #%ecx = i
    cmpl    %eax, %ecx
    jge    done
L1:    pushl    A(,%ecx,4)
    pushl    %ecx
    pushl    $str
    call    printf
    addl    $12, %esp
    incl    -8(%ebp)
    movl    -4(%ebp), %eax    #%eax = n
    movl    -8(%ebp), %ecx  #%ebx = i
    cmpl    %eax, %ecx
    jl    L1    
done:    
    leave
    ret
  


  • 0

#7 Chall

Chall

    CC Addict

  • Senior Member
  • PipPipPipPipPip
  • 349 posts
  • Location:Cedar Rapids, IA
  • Programming Language:Java
  • Learning:C, Java, C++, C#, Python, JavaScript, Assembly

Posted 01 November 2012 - 07:43 PM


1) loop is an instruction, don't use it as a label name. Pick something else.

2) You can't use EBX like that. According to conventions you have to save EBX, ESI, EDI, and EBP before using them in your function, and you must restore their values before returning. You can freely use EAX, EDX, and ECX. You can't expect these registers to have the same values after you call a function.

As for efficiency, I'd fix these things first and then try optimizing it.

So I changed the label name for my loop and I used register EAX in place of register EBX. Do you have any code snippits of saving/restoring registers EBX,ESI, EDI, EBP? I can't seam to find any illustrations of this.
.data
.align 4
A: .long 1,2,3,4,5

.section .rodata
str: .string "A[%d] = %d"
ebxcontents: .string "ecx = %d \n"
eaxcontents: .string "eax = %d\n"
.text
.global main
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $5, -4(%ebp) #n = 5
movl $0, -8(%ebp) #i = 0


movl -4(%ebp), %eax #%eax = n
movl -8(%ebp), %ecx #%ecx = i
cmpl %eax, %ecx
jge done
L1: pushl A(,%ecx,4)
pushl %ecx
pushl $str
call printf
addl $12, %esp
incl -8(%ebp)
movl -4(%ebp), %eax #%eax = n
movl -8(%ebp), %ecx #%ebx = i
cmpl %eax, %ecx
jl L1
done:
leave
ret



I don't have any snippets, but I'm pretty sure it's done through pushing and popping data on the stack. push the values of the registers that are likely to change, and when your function is through, pop them back into their registers when needed.

If you are new to assembly, and are using Linux, you should check out the book "Programming from the ground up". There are free versions online that you can download, and It's a good resource for learning how a computer works, and it also teaches you quite a bit about assembly (on Linux, but principles apply elswere)
  • 0
Speaks fluent Java

#8 restin84

restin84

    CC Resident

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

Posted 01 November 2012 - 08:04 PM

So since I replaced
movl -8(%ebp), %ebx 
with
movl -8(%ebp), %ecx 
If I had used EBX instead then prior to...
L1: pushl A(,%ecx,4)
I should have said
pushl	    %ebx
and after
addl $12, %esp
I should have
popl %ebx
Is this right? But I guess I should use EBX only if I HAVE TO then?
  • 0

#9 Chall

Chall

    CC Addict

  • Senior Member
  • PipPipPipPipPip
  • 349 posts
  • Location:Cedar Rapids, IA
  • Programming Language:Java
  • Learning:C, Java, C++, C#, Python, JavaScript, Assembly

Posted 01 November 2012 - 08:09 PM

So since I replaced

movl -8(%ebp), %ebx
with
movl -8(%ebp), %ecx
If I had used EBX instead then prior to...
L1: pushl A(,%ecx,4)
I should have said
pushl	 %ebx
and after
addl $12, %esp
I should have
popl %ebx
Is this right? But I guess I should use EBX only if I HAVE TO then?

I'm not very good, and I cannot understand that (I'm VERY not good), but I do think you should read this:

A Function Example
Let’s take a look at how a function call works in a real program. The function we are going to
write is the power function. We will give the power function two parameters - the number and
the power we want to raise it to. For example, if we gave it the paramters 2 and 3, it would raise 2
to the power of 3, or 2*2*2, giving 8. In order to make this program simple, we will only allow
numbers 1 and greater.
The following is the code for the complete program. As usual, an explanation follows. Name the
file power.s.
#PURPOSE:
Program to illustrate how functions work
#
This program will compute the value of
#
2^3 + 5^2
#
#Everything in the main program is stored in registers,
#so the data section doesn’t have anything.
.section .data
.section .text
.globl _start
_start:
pushl $3
pushl $2
call power
addl $8, %esp
pushl %eax
pushlpushl$2
$5
#push
second argument
#push
first argument
#call
the function
#move
the stack pointer back
#save the first answer before
#calling the next function
#push second argument
#push first argument
call
power
addl
$8, %esp
popl
%ebx
addl
%eax, %ebx
movl
$1, %eax
int
$0x80
.type power, @function
power:
pushl %ebp
#save old base pointer
movl %esp, %ebp
#make stack pointer the base pointer
subl $4, %esp
#get room for our local storage
movl
8(%ebp), %ebx #put first argument in %eax
movl
12(%ebp), %ecx #put second argument in %ecx
movl
%ebx, -4(%ebp) #store current result
power_loop_start:
cmpl $1, %ecx
#if the power is 1, we are done
je
end_power
movl -4(%ebp), %eax #move the current result into %eax
imull %ebx, %eax
#multiply the current result by
#the base number
movl %eax, -4(%ebp) #store the current result
decl
%ecx
#decrease the power
jmp
power_loop_start #run for the next power
end_power:
movl -4(%ebp), %eax
movl %ebp, %esp
popl %ebp
ret
#return value goes in %eax
#restore the stack pointer
#restore the base pointer

Type in the program, assemble it, and run it. Try calling power for different values, but remember
that the result has to be less than 256 when it is passed back to the operating system. Also try
subtracting the results of the two computations. Try adding a third call to the power function, and
add it’s result back in.
The main program code is pretty simple. You push the arguments onto the stack, call the
function, and then move the stack pointer back. The result is stored in %eax. Note that between
the two calls to power, we save the first value onto the stack. This is because the only register
that is guaranteed to be saved is %ebp. Therefore we push the value onto the stack, and pop the
value back off after the second function call is complete.
Let’s look at how the function itself is written. Notice that before the function, there is
documentation as to what the function does, what it’s arguments are, and what it gives as a return
value. This is useful for programmers who use this function. This is the function’s interface. This
lets the programmer know what values are needed on the stack, and what will be in %eax at the
end.
We then have the following line:
.type power,@function
This tells the linker that the symbol power should be treated as a function. Since this program is
only in one file, it would work just the same with this left out. However, it is good practice.
After that, we define the value of the power label:
44
power:
Chapter 4. All About Functions
As mentioned previously, this defines the symbol power to be the address where the instructions
following the label begin. This is how call power works. It transfers control to this spot of the
program. The difference between call and jmp is that call also pushes the return address onto
the stack so that the function can return, while the jmp does not.
Next, we have our instructions to set up our function:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
At this point, our stack looks like this:
Base Number
<---
12(%ebp)
Power
<---
8(%ebp)
Return Address
<---
4(%ebp)
Old %ebp
<---
(%ebp)
Current result
<---
-4(%ebp) and (%esp)
Although we could use a register for temporary storage, this program uses a local variable in
order to show how to set it up. Often times there just aren’t enough registers to store everything,
so you have to offload them into local variables. Other times, your function will need to call
another function and send it a pointer to some of your data. You can’t have a pointer to a register,
so you have to store it in a local variable in order to send a pointer to it.
Basically, what the program does is start with the base number, and store it both as the multiplier
(stored in %ebx) and the current value (stored in -4(%ebp)). It also has the power stored in %ecx
It then continually multiplies the current value by the multiplier, decreases the power, and leaves
the loop if the power (in %ecx) gets down to 1.

-Taken from Programming from the ground up.

Sorry for the formatting problem.
  • 0
Speaks fluent Java

#10 dargueta

dargueta

    I chown trolls.

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

Posted 04 November 2012 - 11:30 PM

Correct, only use EBX if you have to, and save them before you use them. I usually do something like this:

push    ebp
mov     ebp, esp
push    ebx
sub     esp, 8
.
.
.
add     esp, 8
pop     ebx
pop     ebp
ret

  • 0

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






Also tagged with one or more of these keywords: registering

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