Hi  :P It's possible to say to me how to convert the code below (c++) to ASM? There are some things like parameter passage between functions that i don't understand. Where could i find good documentation about this?
Joanne :oops:
#include <iostream.h>

void calc_sum(int n, int *sump);

int main(){
int sump[20];

calc_sum(20,sump);

for(int i = 0; i < 20; i++)
cout<<sump<<endl;

return 0;

}

void calc_sum(int n, int *sump){

int i, sum=0;

for(i=0; i < n; i++){

sum+=i;

sump=sum;

}

}
Posted on 2006-11-18 10:18:57 by Joanne
"cl /FAs file.cpp" :-)

Sorry that I don't have time for giving some real help, I'm on my way out.
Posted on 2006-11-18 10:57:01 by f0dder
Which assembler are you using? That would help us alot.
Posted on 2006-11-18 20:16:23 by roticv
Joanne,

Hi   It's possible to say to me how to convert the code below (c++) to ASM?


     Yes.

There are some things like parameter passage between functions that i don't understand.


     See the example below in the attached ZIP file.

Where could i find good documentation about this?


     Other than Iczelion's tutorials, and whatever you can find on the forums, I don't know. 

     Here is a MASM example which approximates what you are trying to do.  It passes to a subroutine the address of the array and its length.  The subroutine adds the numbers in the array and returns the sum in EAX.  Look carefully at the build file.  Notice that since this a console application, the link processor has the /SUBSYSTEM:CONSOLE option instead of /SUBSYSTEM:WINDOWS.  The parameters are passed by pushing them onto the stack.  You can follow what is happening by stepping through the program with a good debugger like OllyDbg.  Ask if you have any questions.  Ratch
Attachments:
Posted on 2006-11-18 20:57:09 by Ratch
Hello to all!  :)
The assembler i'm using is the nasm (vs. 0.98.39) one. Thanks Ratch, i'm going to study your sample.
Kiss  ;)
Posted on 2006-11-19 06:08:09 by Joanne
Hi again!
Ratch, i've been looking to your code to make the sum but... i don't understand lot's of instructions  :sad: Maybe because i'm learning the basis of assembly language and the assembler version i'm using is a little bit old  :) Could you translate your code to my assembler version? (nasm vs 0.98.39) I'll wait for your response  :D
Posted on 2006-11-19 15:59:43 by Joanne
Joanne,

...Could you translate your code to my assembler version?...


    Sorry, but I only know and do MASM. If you could point out the areas where you are having probs, maybe I or someone else can help.  Ratch
Posted on 2006-11-19 16:13:42 by Ratch

Could you translate your code to my assembler version? (nasm vs 0.98.39) I'll wait for your response  :D


If you want to start converting that particular piece of MASM(32) code, then take a look at NASM32 ;)
Posted on 2006-11-19 16:22:15 by SpooK
Hello!
I'll try myself to translate your code to my assembler version. The great diference i'm paying atention  is on the way you pass the array and lenght to the stack. The instructions used in your assembler version are of a recent version of assembler :) . Best regards and thank you for your fast response. OK Spook, i'll look that link :)
Posted on 2006-11-19 16:27:02 by Joanne
Hi again! I hope i'm not being boring with this "simple" (not for me  :roll: ) question... I've tryed to make the program by myself, but the problem arises when i want to manipulate the array with the stack. The code i've done is presented next:
%include "asm_io.inc"

segment .data

segment .bss

array resd 20

segment .text
        global  _asm_main
        global sum
       
_asm_main: 

        enter  0,0              ; setup routine
        pusha

        mov ecx, 0
       
fill_array:

        cmp ecx, 19
        ja end
       
        mov , ecx
       
        inc ecx
       
        jmp fill_array
       
end:

        mov eax, 20
        push eax
                            ; MY PROBLEM STARTS HERE!!!
        lea eax,
        push eax
       
        call sum
       
        ; ???? - after calling sum function, i need to deallocate memory on the stack?       

        popa
        mov    eax, 0            ; return back to C
        leave                   
        ret

sum:

        push ebp
        mov ebp, esp
       
        ; ???? - here, i need to allocate memory to all the array?
       
        ; How could i access the elements of the array in a correct way?
       
       
       
       
       
        mov esp, ebp
        pop ebp
       
        ret
Posted on 2006-11-20 04:53:25 by Joanne
I see a procedural stack frame.. surely "Sum" is meant to be defined as a procedure.. then you're doing it 'the hard way' by declaring the stack frame yourself..

Before you call 'Sum', you're pushing the address of the array.. it might look something like this:


sum proc pArray:ptr DWORD
(some code here)
ret
sum endp


Your assembler will write the stack frame FOR you, pushing ebp etc..
but if you insist on doing things the hard way, you'll find that the first and only parameter to your pseudo-procedure is at ebp+8 (after you enter the stackframe via push ebp..mov ebp,esp)

Also, I note that you are writing dwords to the array, but only incrementing the counter (ecx) by one.. this is not correct.
Either write bytes to the array, or increment the counter by 4 (size of dword) depending on what you intended ..

Hope this was helpful :)
Posted on 2006-11-20 06:08:46 by Homer
Hi Homer!
The objective of my code is to make the program i post here at first (in c++). I've made the changes to the code that you've sugested, but it continues to give me an error. For example, i was trying to access the value of the array that was at the memory position on the stack like:mov al, and then, print it out to the screen, but the following error appear:
58368
Exiting due to signal SIGFPE
Division by Zero at eip=0000182d, x87 status=0000
eax=0000009b ebx=10000000 ecx=00000298 edx=00091768 esi=00000014 edi=0000e410
ebp=00000000 esp=000117cb program=D:\SUMPROG.EXE
cs: sel=01a7  base=02980000  limit=0009ffff
ds: sel=01af  base=02980000  limit=0009ffff
es: sel=0000
fs: sel=017f  base=0000fb00  limit=0000ffff
gs: sel=01bf  base=00000000  limit=0010ffff
ss: sel=01af  base=02980000  limit=0009ffff
App stack: [000917c0..
Posted on 2006-11-20 08:46:15 by Joanne
Foregoing any efficiency, thorough error-checking... and attempting to keep a semi-equivalent output of what a generic C compiler would do...

read and learn...


;Straight NASM code (no includes or macros)

global _main


sump resd 20



;##### Program Entrypoint (global procedure) #####
_main:
;Stack Frame + Registers
push ebp
mov ebp,esp
pusha

;Calculation
push DWORD sump ;*sump
push DWORD 20 ;int n
call calc_sum ;calc_sum()
add esp,8 ;adjust stack after STDCALL + parameters

;Print
;* fill in your printing routine here - scale ECX for DWORD *

;Restore Registers + Stack Frame (STDCALL) and Return with Code 0 (in EAX, as per standard x86 ABI)
popa
mov esp,ebp
pop ebp
xor eax,eax
ret

;##### calc_sum (local procedure, not global) #####
calc_sum:
;Stack Frame + Registers
push ebp
mov ebp,esp
pusha

;Calculate
xor eax,eax ;int sum = 0
xor ecx,ecx ;int i = 0
mov ebx,DWORD ;*sump
.calculate:
add eax,ecx ;sum += i
mov DWORD,eax ;sump = sum
inc ecx ;i++
cmp ecx,DWORD ;i < 20
jl .calculate

;Restore Registers + Stack Frame (STDCALL) and Return
popa
mov esp,ebp
pop ebp
ret


Everyone/anyone, please feel free to correct anything you see explicitly wrong :)

Posted on 2006-11-20 11:07:09 by SpooK
Thank you Spook! Now, i can see what i was doing wrong. There are some procedures that i need to learn better... But your code seems exactly what i need. Sorry if i took some time from you, but i'm not a professional  :D I'm learning assembly language slowly, but with some patience, i would reach my objectives.

Thanks again  ;)
Posted on 2006-11-20 11:52:47 by Joanne
Joanne,

    If you already know this, then forgive me.  The following facts will cause you no end of grief if you are not aware of them.

    First, the stack pointer does not increase with a PUSH and decrease with a POP.  Just the opposite happens.  The stack grows toward zero and shrinks toward its highest address.  For instance if the stack allotment is 4K bytes and you PUSH 1000 items (4K/DWORD), the stack pointer (ESP) will point to the lowest relative stack address.  Similarly, a fresh stack will have its highest pointer relative value of 4K.

    Second, the INTEL CPUs use the little endian format for memory storage.  That means that if each 8 bit byte in a 32 bit register is valued 1,2,3,4 , then it will be stored from the register into memory as 4,3,2,1 .  If that memory location is read into another register, the bytes will flip again to 1,2,3,4 .  So  if you specify something like DB 1,2,3,4 and read that location with EAX, then you will get 4,3,2,1 in EAX.  If you specify DD 01020304H, then the assembler will generate each byte backwards into the dword, and a subsequent read into EAX will be 1,2,3,4 .

    Since you are a beginner, you might want to take Homer"s advice and use the PROC method for writing subroutines instead of STRUCs as I do.  PROCs have advantages and disadvantages, but they are simpler.  Sorry I cannot help you with NASM, but you do have a functional executable that you can use with a debugger to see what happens with the transfer of parameters to the stack for the subroutine.  I strongly advise you to do that.  Ratch

Homer,

    As mentioned above, my method does have some advantages.  It does not use EBP in a register starved CPU.  And parameters can be PUSHed ahead of time when they are available instead of storing them somewhere and retrieving them later when the subroutine is called.  The disadvantage is, of course, the stack frame is "floating", and any references to parameters on the stack have to be compensated with respect to any stack changes.  It becomes second nature after awhile to do that, but it is probably too advanced for beginners.  Ratch
   

Posted on 2006-11-20 11:54:03 by Ratch

     Since you are a beginner, you might want to take Homer"s advice and use the PROC method for writing subroutines instead of STRUCs as I do.  PROCs have advantages and disadvantages, but they are simpler.  Sorry I cannot help you with NASM, but you do have a functional executable that you can use with a debugger to see what happens with the transfer of parameters to the stack for the subroutine.  I strongly advise you to do that.  Ratch


NASM32 has a set of includes and macros (nasm32.inc) that helps creating/calling procedures.

The following code is the equivalent program of the one I posted above except using nasm32.inc...


;Straight NASM code (no includes or macros)

global _main


sump resd 20



;##### Program Entrypoint (global procedure) #####
proc _main
;Stack Frame taken care of by "proc" macro

;Calculation
invoke calc_sum, DWORD 20, DWORD sump ;calc_sum(int n, int *sump)

;Print
;* fill in your printing routine here - scale ECX for DWORD *

;Restore Stack Frame (STDCALL) and Return with Code 0 (in EAX, as per standard x86 ABI)
xor eax,eax
ret ;using NASM32.INC, "ret" is actually an overloaded macro instruction, resulting in proper stack clean-up depending on the call
endproc

;##### calc_sum (local procedure, not global) #####
proc calc_sum
;Stack Frame taken care of by "proc" macro

;Calculate
xor eax,eax ;int sum = 0
xor ecx,ecx ;int i = 0
mov ebx,DWORD ;*sump
.calculate:
add eax,ecx ;sum += i
mov DWORD,eax ;sump = sum
inc ecx ;i++
cmp ecx,DWORD ;i < 20
jl .calculate

;Restore Stack Frame (STDCALL) and Return
ret ;using NASM32.INC, "ret" is actually an overloaded macro instruction, resulting in proper stack
endproc


As you can see, stack frame setup and restoration are always consistent in such a generic manner. NASM's macro capabilities help take care of this by cleaning things up with the use of simpler "instructions", and eliminating human error by making sure the right instructions are in the right place.

NASM32.INC also includes macros for using higher-level constructs such as "IF/ELSE/FOR/WHILE" to help ease your transition to lower-level programming.

Learning ASM like this is a common thing. People tend to start off with HLL's such as C/C++ and work their way down to the bare instruction set. Along the way, people make use of macros and pseudo-instructions. When people become more comfortable with their knowledge level, they start to use some of those macros again, to save typing time (a BIG one is the proc/endproc/invoke example).

I haven't used NASM32 in awhile, so there may be some inconsistancies (mostly things missing) from the code above to make it fully assemble properly.
Posted on 2006-11-20 14:18:19 by SpooK
Hello again!
I've already tested your code Spook. I've changed some things and it's now 100% functional. Resources like this are blessed :D
Thanks.
%include "asm_io.inc"
segment .data
;
; initialized data is put in the data segment here
;

segment .bss
;
; uninitialized data is put in the bss segment
;
sump resd 20



segment .text
        global  _asm_main
       
_asm_main:
        enter  0,0              ; setup routine
        pusha
           
        mov ecx, 0   

fill_array:
             
        cmp ecx, 19
        ja continue
       
        mov DWORD, ecx 
       
        inc ecx
       
        jmp fill_array     

continue:

        ;Calculation
        push DWORD sump ;*sump 
        push DWORD 20 ;int n
        call calc_sum ;calc_sum()
        add esp,8 ;adjust stack after STDCALL + parameters
       
        mov ecx, 0
       
present_on_screen:
                 
        cmp ecx, 19
        ja end
       
        mov eax, DWORD
       
        call print_int
        call print_nl
       
        inc ecx
       
        jmp present_on_screen
       
end:                 
           
       
        popa
        mov    eax, 0            ; return back to C
        leave                   
        ret

;##### calc_sum (local procedure, not global) #####
calc_sum:
;Stack Frame + Registers
push ebp
mov ebp,esp
sub esp, 8


;Calculate
xor eax,eax ;int sum = 0
xor ecx,ecx ;int i = 0
mov ebx,DWORD ;*sump 

.calculate:
add eax,ecx ;sum += i
mov DWORD,eax ;sump = sum
inc ecx ;i++
cmp ecx,DWORD ;i < 20
jl .calculate

;Restore Registers + Stack Frame (STDCALL) and Return

mov esp,ebp
pop ebp
ret

Posted on 2006-11-20 15:29:33 by Joanne
Hi:
Check this for details:
http://maven.smith.edu/~thiebaut/ArtOfAssembly/CH11/CH11-1.html

It's very detailed in the mechanism of Procedures and Functions in Assembly, though using 16-bits address mode,  the concept is the same.

How I wish  x86 ASM Wiki book could cover this.
I've waited for 6 months, but the content of chapter "Sub Programs: Code reuse and procedures" is still empty.
Posted on 2006-11-20 18:16:11 by guidry