Difference between revisions of "CSC231 No-no! and Be-Careful! situations"

From dftwiki3
Jump to: navigation, search
(What's tricky about the following code?)
(Helpful Trick)
 
(19 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">
  
<code><pre>
+
; this function will compute N results and store them in the stack...
 
 
;------------------------------------------------------------------
 
; function that pushes several results in the stack
 
;------------------------------------------------------------------
 
 
compute:
 
compute:
 
         pushad
 
         pushad
Line 24: Line 23:
 
         ret
 
         ret
  
</pre></code>
+
</source>
  
=What's tricky about the following code?=
+
<br />
  
<code><pre>
+
=Code to be Avoided...=
 +
<br />
 +
Why should we avoid coding functions as shown below?
 +
<br />
 +
<source lang="asm">
 
compute:
 
compute:
 
         pushad
 
         pushad
push ebx
+
push ebp
         mov ebx, esp
+
         mov ebp, esp
  
 
;;; get parameters from the stack                                                                                       
 
;;; get parameters from the stack                                                                                       
Line 45: Line 48:
  
 
;;; we're done                                                                                                           
 
;;; we're done                                                                                                           
         pop ebx
+
         pop ebp
 
         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
 +
;; -------------------------
  
</pre></code>
+
section .text
 +
global _start
  
<br />
+
_start:
<br />
+
push eax ; make room in the stack for result
<br />
+
push dword [a] ; pass copy of a
<br />
+
push dword [b] ; pass copy of b
<br />
+
call sum
<br />
+
pop dword [result] ; get sum from stack and restore stack
<br />
+
;; 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