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++


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


Posted on 2010-02-20 12:00:04 by snoopyromeo
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:

	;; 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
Posted on 2010-02-20 12:56:20 by Synfire
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

Posted on 2010-02-20 22:55:06 by fbkotler