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

From dftwiki3
Jump to: navigation, search
(Helpful Trick)
(Helpful Trick)
 
(10 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 />
<code><pre>
+
<source lang="asm">
  
 
; this function will compute N results and store them in the stack...
 
; this function will compute N results and store them in the stack...
Line 22: 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
Line 46: Line 51:
 
         popad
 
         popad
 
         ret 3*4
 
         ret 3*4
</pre></code>
+
</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]
 
* 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
;;; openFile( filename, handle )
+
a dd 0x1234 ; operand 1
;;; opens a file for reading, puts handle in dword whose address
+
b dd 0x5555 ; operand 2
;;; is passed in stack.
+
result dd 0 ; where sum will end up
  ;;; Does not modify the registers, but modifies flags.
+
 
openFile:
+
;; -------------------------
        push    ebp
+
;; code area
         mov    ebp, esp
+
;; -------------------------
         pushad
+
 
       
+
section .text
  '''%define of_fileName dword[ebp+12]'''
+
global _start
'''%define of_handle  dword[ebp+8]'''
+
 
          
+
_start:
         mov    eax,SYS_OPEN
+
push eax ; make room in the stack for result
         mov    ebx, '''of_fileName'''
+
push dword [a] ; pass copy of a
         mov    ecx, O_RDONLY
+
push dword [b] ; pass copy of b
         mov    edx, S_IRUSR|S_IWUSR|S_IXUSR
+
call sum
        int    0x80
+
pop dword [result] ; get sum from stack and restore stack
   
+
;; exit()
         test    eax,eax
+
 
         jns    .fileOk
+
mov eax,SYS_EXIT
        print2  "Error opening file"
+
mov ebx,0
         mov    eax, SYS_EXIT
+
int 0x80 ; final system call
         mov    ebx, 1
+
 
        int    0x80
+
;;; -------------------------------------------------------
+
;;; sum function
.fileOk:
+
;;; gets 2 dwords from stack and puts sum in stack for main
        mov     ebx, '''of_handle'''
+
;;; program to receive.
        mov    [ebx], eax      ; save handle
+
;;; registers modified: eax
        clc                    ; clear carry if ok
+
;;;  
       
+
;;; stack looks like this after first 2 instructions:
  .done:  popad                  ; restore registers
+
;;;
        pop    ebp
+
;;;         +----------+
        ret    8
+
;;;         | "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