Difference between revisions of "CSC231 No-no! and Be-Careful! situations"
(→What's tricky about the following code?) |
(→Helpful Trick) |
||
(7 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"> | <source lang="asm"> | ||
Line 24: | Line 25: | ||
</source> | </source> | ||
− | + | <br /> | |
+ | =Code to be Avoided...= | ||
+ | <br /> | ||
+ | Why should we avoid coding functions as shown below? | ||
+ | <br /> | ||
<source lang="asm"> | <source lang="asm"> | ||
compute: | compute: | ||
Line 48: | Line 53: | ||
</source> | </source> | ||
+ | <br /> | ||
=Helpful Trick= | =Helpful Trick= | ||
− | + | <br /> | |
* We can use the '''%define''' directive to assign names to our parameters living in the stack. | * 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] | * More information on %define: [http://www.tortall.net/projects/yasm/manual/html/nasm-preprocessor.html#nasm-macro-define Nasm Preprocessor] | ||
* Example: | * 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