Difference between revisions of "CSC231 No-no! and Be-Careful! situations"
(→Helpful Trick) |
(→Helpful Trick) |
||
(15 intermediate revisions by the same user not shown) | |||
Line 2: | Line 2: | ||
---- | ---- | ||
+ | <br /> | ||
=What's wrong with the following code?= | =What's wrong with the following code?= | ||
+ | <br /> | ||
+ | <source lang="asm"> | ||
− | + | ; this function will compute N results and store them in the stack... | |
− | |||
− | |||
compute: | compute: | ||
pushad | pushad | ||
Line 22: | Line 23: | ||
ret | ret | ||
− | </ | + | </source> |
− | + | <br /> | |
− | < | + | =Code to be Avoided...= |
+ | <br /> | ||
+ | Why should we avoid coding functions as shown below? | ||
+ | <br /> | ||
+ | <source lang="asm"> | ||
compute: | compute: | ||
pushad | pushad | ||
Line 46: | Line 51: | ||
popad | popad | ||
ret 3*4 | ret 3*4 | ||
+ | </source> | ||
+ | <br /> | ||
+ | =Helpful Trick= | ||
+ | <br /> | ||
+ | * We can use the '''%define''' directive to assign names to our parameters living in the stack. | ||
+ | * More information on %define: [http://www.tortall.net/projects/yasm/manual/html/nasm-preprocessor.html#nasm-macro-define Nasm Preprocessor] | ||
+ | * Example: | ||
+ | <br /> | ||
+ | :::<source lang="asm" highlight="71, 72, 73, 75, 76,77"> | ||
+ | ;;; sumproc3.asm | ||
+ | ;;; D. Thiebaut CSC231 | ||
+ | ;;; third of a series of programs illustrating how to pass and receive | ||
+ | ;;; information to and from a function in assembly. | ||
+ | ;;; | ||
+ | ;;; This and all associated programs simply add the contents of | ||
+ | ;;; two variables a and b and store the resulting sum in a variable | ||
+ | ;;; called result (all are double words) | ||
+ | ;;; | ||
+ | ;;; this version passes a and b by value through the stack. the | ||
+ | ;;; sum is passed back in the stack. | ||
+ | SYS_EXIT equ 1 | ||
+ | SYS_WRITE equ 4 | ||
+ | STDOUT equ 1 | ||
+ | ;; ------------------------- | ||
+ | ;; data segment | ||
+ | ;; ------------------------- | ||
+ | section .data | ||
+ | a dd 0x1234 ; operand 1 | ||
+ | b dd 0x5555 ; operand 2 | ||
+ | result dd 0 ; where sum will end up | ||
+ | ;; ------------------------- | ||
+ | ;; code area | ||
+ | ;; ------------------------- | ||
− | + | section .text | |
− | + | global _start | |
− | |||
− | + | _start: | |
− | + | push eax ; make room in the stack for result | |
+ | push dword [a] ; pass copy of a | ||
+ | push dword [b] ; pass copy of b | ||
+ | call sum | ||
+ | pop dword [result] ; get sum from stack and restore stack | ||
+ | ;; exit() | ||
+ | mov eax,SYS_EXIT | ||
+ | mov ebx,0 | ||
+ | int 0x80 ; final system call | ||
− | ;;; | + | ;;; ------------------------------------------------------- |
− | ;;; | + | ;;; sum function |
− | ;;; | + | ;;; gets 2 dwords from stack and puts sum in stack for main |
− | ;;; | + | ;;; program to receive. |
− | ;;; | + | ;;; registers modified: eax |
− | + | ;;; | |
− | + | ;;; stack looks like this after first 2 instructions: | |
− | + | ;;; | |
− | + | ;;; +----------+ | |
− | + | ;;; | "empty" | <-- ebp+16 | |
− | + | ;;; +----------+ | |
− | + | ;;; |copy of a | <-- ebp+12 | |
− | + | ;;; +----------+ | |
− | + | ;;; |copy of b | <-- ebp+8 | |
− | + | ;;; +----------+ | |
− | + | ;;; |retrn addr| <-- ebp+4 (plus 4 because double words!) | |
− | + | ;;; +----------+ | |
− | + | ;;; |"old" ebp | <-- ebp <-- esp | |
+ | ;;; +----------+ | ||
+ | ;;; | | | ||
+ | |||
+ | ;;; ------------------------------------------------------- | ||
+ | sum: push ebp | ||
+ | mov ebp,esp | ||
− | + | %define sum_a dword[ebp+12] | |
− | + | %define sum_b dword[ebp+8] | |
− | + | %define sum_res dword[ebp+16] | |
− | |||
− | |||
− | |||
− | + | mov eax,sum_b ; get copy of b | |
− | + | add eax,sum_a ; get copy of a | |
− | + | mov sum_res,eax ; put sum in reserved space in stack | |
− | + | ||
− | + | pop ebp | |
− | + | ret 8 ; we get rid of 2 dwords in stack and | |
− | + | ; keep one for main program to get sum | |
− | |||
− | + | </source> | |
− | </ | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<br /> | <br /> | ||
<br /> | <br /> |
Latest revision as of 07:33, 30 October 2014
--D. Thiebaut 13:15, 10 November 2010 (UTC)
What's wrong with the following code?
; this function will compute N results and store them in the stack...
compute:
pushad
mov ecx, N ;loop some number of times
mov eax, data1 ;get some data
mov ebx, data2
.for: call doSomething ;operate on eax and ebx
; on return, eax contains
; result we're interested in
push eax ;save result in stack
loop .for
;;; we're done
popad
ret
Code to be Avoided...
Why should we avoid coding functions as shown below?
compute:
pushad
push ebp
mov ebp, esp
;;; get parameters from the stack
mov ecx,[ebp+XX] ;XX is some offset
mov eax,[ebp+YY] ;YY is some offset
mov ebx,[ebp+ZZ] ;ZZ is some offset
.for: call doSomething ;operate on eax and ebx
; on return, eax contains
; result we're interested in
loop .for
;;; we're done
pop ebp
popad
ret 3*4
Helpful Trick
- We can use the %define directive to assign names to our parameters living in the stack.
- More information on %define: Nasm Preprocessor
- Example:
;;; sumproc3.asm ;;; D. Thiebaut CSC231 ;;; third of a series of programs illustrating how to pass and receive ;;; information to and from a function in assembly. ;;; ;;; This and all associated programs simply add the contents of ;;; two variables a and b and store the resulting sum in a variable ;;; called result (all are double words) ;;; ;;; this version passes a and b by value through the stack. the ;;; sum is passed back in the stack. SYS_EXIT equ 1 SYS_WRITE equ 4 STDOUT equ 1 ;; ------------------------- ;; data segment ;; ------------------------- section .data a dd 0x1234 ; operand 1 b dd 0x5555 ; operand 2 result dd 0 ; where sum will end up ;; ------------------------- ;; code area ;; ------------------------- section .text global _start _start: push eax ; make room in the stack for result push dword [a] ; pass copy of a push dword [b] ; pass copy of b call sum pop dword [result] ; get sum from stack and restore stack ;; exit() mov eax,SYS_EXIT mov ebx,0 int 0x80 ; final system call ;;; ------------------------------------------------------- ;;; sum function ;;; gets 2 dwords from stack and puts sum in stack for main ;;; program to receive. ;;; registers modified: eax ;;; ;;; stack looks like this after first 2 instructions: ;;; ;;; +----------+ ;;; | "empty" | <-- ebp+16 ;;; +----------+ ;;; |copy of a | <-- ebp+12 ;;; +----------+ ;;; |copy of b | <-- ebp+8 ;;; +----------+ ;;; |retrn addr| <-- ebp+4 (plus 4 because double words!) ;;; +----------+ ;;; |"old" ebp | <-- ebp <-- esp ;;; +----------+ ;;; | | ;;; ------------------------------------------------------- sum: push ebp mov ebp,esp %define sum_a dword[ebp+12] %define sum_b dword[ebp+8] %define sum_res dword[ebp+16] mov eax,sum_b ; get copy of b add eax,sum_a ; get copy of a mov sum_res,eax ; put sum in reserved space in stack pop ebp ret 8 ; we get rid of 2 dwords in stack and ; keep one for main program to get sum