Reputation: 2293
I use Intel x86 for assembler programming. I've got two variables (int), and I want the assembler function to return the biggest. I call the assembler function with a C program, and I've got this in the main(), function(1,5).
Here is the assembler code:
.globl function
.data
var1: .long 0
var2: .long 0
.text
function:
movl 4(%esp), %eax
movl 8(%esp), %ebx
cmp %eax, %ebx
jg cond1 /*greater, if a < b */
jl cond2 /*lower, if a > b */
movl var2, %eax
ret
cond1:
movl %eax, var1 /*var1 = a */
movl %ebx, var2 /*var2 = b */
ret
cond2:
movl %eax, var2 /*var2 = a*/
movl %ebx, var1 /*var1 = b */
ret
The biggest number will be in %eax (movl var2, %eax). The problem is that the function always returns the initial number in %eax. For example, function(1,5) returns "1" instead of "5".
I don't understand why the result is wrong.
EDIT : Thanks to your replies, I've modified the program thanks to your advice :
function:
movl 4(%esp), %eax
movl 8(%esp), %ebx
cmp %eax, %ebx
jg cond1 /*greater, if a < b */
jl cond2 /*lower, if a > b */
next:
movl var2, %eax
ret
cond1:
movl %eax, var1 /*var1 = a */
movl %ebx, var2 /*var2 = b */
jmp next
cond2:
movl %eax, var2 /*var2 = a*/
movl %ebx, var1 /*var1 = b */
jmp next
To come-back in function()
, I use jmp
, is it correct?
It works fine.
Also, how can I improve this code? I use variables because the aim will be to have three numbers and find the median one.
Upvotes: 3
Views: 1660
Reputation: 1047
Well, I'm not very familiar with the NASM format (I use MASM), and I haven't done x86 assembly in a while, but it does not look like you are returning anything from your functions (cdecl calling convention I assume). You need to push the return value on to the stack and then do "ret 4" or something like that.
Upvotes: 1
Reputation: 37214
The value returned from the function is typically returned in the EAX register, which in your case never changes after you load it (you only change "var1" and "var2").
For a simplified version (without "var1" and "var2"):
function:
movl 4(%esp), %eax /* EAX = a */
cmpl 8(%esp), %eax /* Is a >= b? */
jge done /* yes, return a (already in EAX) */
movl 8(%esp), %eax /* no, return b */
done:
ret
Upvotes: 2
Reputation: 46998
I think you're confused about what the jg
and jl
instructions are doing.
From your code, my best guess is that you're thinking of them as being approximately equivalent to this C code:
if (condition) cond1();
whereas they actually behave like
if (condition) goto cond1;
So, there are three possible control flow paths through your function:
1) If the jg
branch is taken:
----caller----.
|
v
function:
movl 4(%esp), %eax
movl 8(%esp), %ebx
cmp %eax, %ebx
jg cond1 /*greater, if a < b */
|
branch
|
v
cond1:
movl %eax, var1 /*var1 = a */
movl %ebx, var2 /*var2 = b */
ret
|
return to |
<---caller----'
2) If the jg
branch is not taken, but the jl
branch is taken:
----caller----.
|
v
function:
movl 4(%esp), %eax
movl 8(%esp), %ebx
cmp %eax, %ebx
jg cond1 /*greater, if a < b */
jl cond2 /*lower, if a > b */
|
branch
|
v
cond2:
movl %eax, var2 /*var2 = a*/
movl %ebx, var1 /*var1 = b */
ret
|
return to |
<---caller----'
3) If neither branch is taken -- this is the only path which executes movl var2, %eax
:
----caller----.
|
v
function:
movl 4(%esp), %eax
movl 8(%esp), %ebx
cmp %eax, %ebx
jg cond1 /*greater, if a < b */
jl cond2 /*lower, if a > b */
movl var2, %eax
ret
|
return to |
<---caller----'
Upvotes: 4