this program call a function and uses printf to display the results.
PLease help me with this code. THe program in returning a big number instead of the 10. its returing a=134520852. it should be a=10.
this is the c++
this is the assembly
PLease help me with this code. THe program in returning a big number instead of the 10. its returing a=134520852. it should be a=10.
this is the c++
int sum(int x)
{
int t;
t = x;
return t;
}
int main()
{
int num = 3;
printf("%d", sum(num));
return 0;
}
this is the assembly
extern printf ; the C function to be called
SECTION .data ; Data section
var1 dd 40
a: dd 5 ; int a=5;
fmt: db "a=%d", 10, 0
SECTION .bss
flttmp: resq 1 ; 64-bit temporary for printing flt1
SECTION .text ; Code section.
global main
myfunction:
push ebp
mov ebp, esp
sub esp, 10
mov eax,
mov , eax
mov eax,
mov esp, ebp
pop ebp
ret
main:
push ebp ; set up stack frame
mov ebp,esp
xor ebx, ebx
push 10
call myfunction
push ebx
pop ebx
mov , ebx
push dword var1
push dword fmt
call printf
add esp, 8
mov esp, ebp ; takedown stack frame
pop ebp ; same as "leave" op
mov eax, 0
ret
I know people make a big deal about learning the stack layout, and YES it is important (which is honestly where you made your error). But I've found it to be a good idea to represent the stack with structures and create @ARG and @VAR defines at the beginning of my code to specify the starting point of arguments and locals. Reason being is that this can change depending on if you are using 16-bit, 32-bit, or 64-bit mode (and can be easily made portable using %if and __BITS__ constructs in NASM). Also, for example, if you decide to change the size of a variable or argument in a procedure, updating your procedure is much easier (just modifying the structure rather than a full update of the procedure). Check out the following code:
Also take note that MyFunction is written using StdCall calling convention whereas main is CDECL calling convention. StdCall has the procedure clean up the stack and is generally a much more optimal strategy when you know how many arguments are being used. This difference of calling convention explains why the prologue for these procedures are different.
I am by no means telling you to forget learning about the stack layout. You NEED to learn the stack layout. But using the old style of accessing values just obfuscates your code, not so much in yours but when working with a bunch of local variables (some which could be structures like WNDCLASSEX which has bunch of elements) paired with the fact that people who do this rarely comment those lines do make updating it more difficult later on and horrible on 3rd party readers of your code.
Regards,
Bryant Keller
;; Build with:
;; nasm -f elf -o test.o test.asm
;; gcc -o test test.o
;; Execution:
;; $ ./test
;; a=10
;; $
BITS 32
%define @ARG Ebp + 8
%define @VAR Ebp - 8
%define SizeOf(_x_) _x_ %+ _size
EXTERN printf
GLOBAL main
%macro CCall 1-*
%push
%define %%proc %1
%assign %$ii 0
%rep %0-1
%rotate -1
Push DWORD %1
%assign %$ii %$ii + 1
%endrep
Call %%proc
Add Esp, ( 4 * %$ii )
%pop
%endm
%macro StdCall 1-*
%push
%define %%proc %1
%rep %0-1
%rotate -1
Push DWORD %1
%endrep
Call %%proc
%pop
%endm
SECTION .data
strFormat DB "a=%d", 10, 0
SECTION .text
MyFunction:
STRUC MFA
.x RESD 1
ENDSTRUC
STRUC MFL
.t RESD 1
ENDSTRUC
Push Ebp
Mov Ebp, Esp
Sub Esp, SizeOf( MFL )
;; --[ Store Argument in Eax ]--
; Mov Eax,
;; --
Mov Eax, [@ARG + MFA.x]
;; --[ Store Eax in Local ]--
; Mov , Eax
;; --
Mov [@VAR - MFL.t], Eax
;; --[ Store Local in Eax ]--
; Mov Eax,
;; --
Mov Eax, [@VAR - MFL.t]
Leave
Ret SizeOf( MFA )
main:
STRUC ENV
.argc RESD 1
.argv RESD 1
.envp RESD 1
ENDSTRUC
Push Ebp
Mov Ebp, Esp
StdCall MyFunction, 10
CCall printf, strFormat, Eax
Leave
Ret
Also take note that MyFunction is written using StdCall calling convention whereas main is CDECL calling convention. StdCall has the procedure clean up the stack and is generally a much more optimal strategy when you know how many arguments are being used. This difference of calling convention explains why the prologue for these procedures are different.
I am by no means telling you to forget learning about the stack layout. You NEED to learn the stack layout. But using the old style of accessing values just obfuscates your code, not so much in yours but when working with a bunch of local variables (some which could be structures like WNDCLASSEX which has bunch of elements) paired with the fact that people who do this rarely comment those lines do make updating it more difficult later on and horrible on 3rd party readers of your code.
Regards,
Bryant Keller
That may all be true, but the main problem is "push dword var1". That's the address of your variable - the big number you're seeing. You want "push dword ", the "" of the variable. That would show zero. You've zeroed ebx, pushed it and popped it, and put it in "". Still zero. The result of "myfunction" (in eax) never gets used.
Since C expects ebx to be preserved across a function call, altering it may cause your program to crash after the "ret".
Best,
Frank
Since C expects ebx to be preserved across a function call, altering it may cause your program to crash after the "ret".
Best,
Frank