Transcript Assembly 07

Assembly 07
Outline
•
•
•
•
•
•
•
•
1
Boxes within Boxes
Procedure Definition
call, ret
Saving / Restoring Registers
Argument(s)
Return Value(s)
Global vs. Local Data
Accidental Recursion
Boxes within Boxes
• Procedures help manage code complexity
• Procedures make code more:
• Readable
• Maintainable
• Reusable
2
What does
this code do
again?
Boxes within Boxes
• Unlike high-level languages, assembly does not “ship” with
built-in procedures (e.g., printf in C++)
• You have to write your own procedures
• Read from file
• Write to file
• Etc.
3
Boxes within Boxes
• Book uses example of “getting up in the morning”
•
•
•
•
•
•
4
Shut off clock radio
Climb out of bed
Let dogs out
Eat breakfast
Brush your teeth
Shower
Boxes within Boxes
• Each task can be divided into smaller tasks:
• E.g., Brushing your teeth:
•
•
•
•
Pick up toothpaste
Unscrew cap
Place cap on sink counter
…
• Same idea with procedures
• Divide tasks into subtasks
5
Outline
•
•
•
•
•
•
•
•
6
Boxes within Boxes
Procedure Definition
call, ret
Saving / Restoring Registers
Argument(s)
Return Value(s)
Global vs. Local Data
Accidental Recursion
Procedure Definition
• Must begin with a label
• Must have at least one ret (return)
• E.g.,
my_print:
<instruction>
<instruction>
ret
7
; label for “my_print” proc
; some instruction
; some instruction
; return
Outline
•
•
•
•
•
•
•
•
8
Boxes within Boxes
Procedure Definition
call, ret
Saving / Restoring Registers
Argument(s)
Return Value(s)
Global vs. Local Data
Accidental Recursion
call Mnemonic
call
->
used to invoke the procedure
usage:
call <procedure_name>;
9
ret Mnemonic
ret
usage:
ret
10
->
;
;
returns from procedure
takes no operands
returns to instruction after call
call / ret Mnemonics
• call puts esp onto stack
• esp has address of next instruction (after call)
• ret pops esp from stack
• Execution resumes at the instruction after call
11
stack
1. instruction
executes
my_print:
<instruction>;
<instruction>;
ret;
esp
<instruction>;
call my_print;
12
<next instr>;
…
stack
2. call to
my_print made
my_print:
<instruction>;
<instruction>;
ret;
<instruction>;
esp
13
call my_print;
<next instr>;
…
3. esp+1 value
pushed to stack
stack
address of <next instr>;
my_print:
<instruction>;
<instruction>;
ret;
<instruction>;
esp
14
call my_print;
<next instr>;
…
4. flow of
execution goes
to my_print
stack
address of <next instr>;
my_print:
esp
<instruction>;
<instruction>;
ret;
<instruction>;
call my_print;
15
<next instr>;
…
5. my_print
executes
stack
address of <next instr>;
my_print:
<instruction>;
esp
<instruction>;
ret;
<instruction>;
call my_print;
16
<next instr>;
…
6. ret (return)
reached in
my_print
stack
address of <next instr>;
my_print:
<instruction>;
<instruction>;
esp
ret;
<instruction>;
call my_print;
17
<next instr>;
…
stack
7. Address
popped off
stack
address of <next instr>;
8. esp set to
address
my_print:
<instruction>;
<instruction>;
esp
ret;
<instruction>;
call my_print;
18
<next instr>;
…
9. Flow of
execution
continues at
instruction after
call
stack
my_print:
<instruction>;
<instruction>;
ret;
<instruction>;
call my_print;
esp
19
<next instr>;
…
stack
10. Flow of
execution
continues…
my_print:
<instruction>;
<instruction>;
ret;
<instruction>;
call my_print;
<next instr>;
20
esp
…
stack
return address
return address
return address
return address
return address
Every time you make a call, the stack grows by 32
bits.
Why??
21
stack
return address
return address
return address
Every time you return from a procedure (with ret), the
stack shrinks by 32 bits.
22
msg: db “Hello There!!!”,10
msgLen: equ $-msg
;
;
in .data
in .data
call my_print
call my_print
call my_print
;
;
;
in .text
in .text
in .text
my_print:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, msgLen
int 0x80
ret
; in .text
; make sys_write call
; write to stdout
; write contents of msg
; number of bytes to write
; make system call
; return
call / ret Mnemonics
UNIX> ./a.out
Hello World!!!
Hello World!!!
Hello World!!!
UNIX>
24
msg: db “Hello There!!!”,10
msgLen: equ $-msg
call my_print
call my_print
call my_print
my_print:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, msgLen
int 0x80
ret
Outline
•
•
•
•
•
•
•
•
25
Boxes within Boxes
Procedure Definition
call, ret
Saving / Restoring Registers
Argument(s)
Return Value(s)
Global vs. Local Data
Accidental Recursion
Saving Register Values
• What is the result of add eax, ebx?
mov eax, 42;
mov ebx, 58;
call my_print;
add eax, ebx;
26
Saving Register Values
mov eax, 42;
mov ebx, 58;
call my_print;
add eax, ebx;
27
eax
ebx
Saving Register Values
mov eax, 42;
mov ebx, 58;
call my_print;
add eax, ebx;
28
eax
42
ebx
58
Saving Register Values
mov eax, 42;
mov ebx, 58;
call my_print;
add eax, ebx;
eax
4
ebx
1
my_print sets eax to “4” for sys_write
my_print sets ebx to “1” for stdout
29
Saving Register Values
mov eax, 42;
mov ebx, 58;
call my_print;
add eax, ebx;
eax
5
ebx
1
were we expecting “5” or “100”??
30
Saving Register Values
• Often important to save registers before calling a procedure
• Guards against bugs that are extremely hard to track down
spooky
31
Saving Register Values
• Use the stack to save registers
• Push registers onto stack before procedure call
• Pop registers off of stack after procedure returns
• Be mindful of order!
• Last In First Out
32
Saving Register Values
• If you “own” the procedure code, you can push / pop registers
within the procedure
• Push registers at beginning of procedure
• Pop registers at end of procedure
33
Saving Register Values
mov eax, 42;
mov ebx, 58;
pushad;
call my_print;
popad;
add eax, ebx;
34
eax
ebx
Saving Register Values
mov eax, 42;
mov ebx, 58;
pushad;
call my_print;
popad;
add eax, ebx;
35
eax
42
ebx
58
Saving Register Values
mov eax, 42;
mov ebx, 58;
pushad;
call my_print;
popad;
add eax, ebx;
36
eax
42
ebx
58
all 32-bit GP
registers
pushed to
stack
Saving Register Values
mov eax, 42;
mov ebx, 58;
pushad;
call my_print;
popad;
add eax, ebx;
37
eax
4
ebx
1
Saving Register Values
mov eax, 42;
mov ebx, 58;
pushad;
call my_print;
popad;
add eax, ebx;
38
eax
42
ebx
58
pop all 32-bit
registers from
stack back to
registers
Saving Register Values
mov eax, 42;
mov ebx, 58;
pushad;
call my_print;
popad;
add eax, ebx;
39
eax
100
ebx
58
Outline
•
•
•
•
•
•
•
•
40
Boxes within Boxes
Procedure Definition
call, ret
Saving / Restoring Registers
Argument(s)
Return Value(s)
Global vs. Local Data
Accidental Recursion
Passing Arguments
• How do you pass arguments to assembly procedures?
• … and no, this is not a setup for a hilarious joke…
• Use registers!
• Caller puts arguments into pre-ordained registers
• E.g., eax is argument 1, ebx is argument 2, etc.
• Important to clearly comment your procedures!!
• Especially expectations for arguments
• E.g., integer in eax, pointer in ebx, etc.
41
Passing Arguments
• Example: procedure to add two numbers, print result to stdout
• Numbers will be arguments to procedure
• Simplified version: only prints results between 0 and 9…
• Printing results > 10 may be part of your homework…
42
SIZE: equ 10
output: resb SIZE
mov eax, 2
mov ebx, 3
call my_add
; in .data
; in .bss
; below in .text
; argument 1 in eax
; argument 2 in ebx
; invoke procedure to add/print
my_add:
; procedure to add / print result
add eax, ebx
; add arguments
add eax, ‘0’
; convert to ASCII number
mov [output], eax; ; put result in output buffer
mov byte [output+1], 10 ; add carriage return
call my_print
; write output buffer to stdout
ret
; return to caller
Procedure Arguments
UNIX> ./a.out
5
UNIX>
msg: SIZE: equ 10
output: resb SIZE
mov eax, 2
mov ebx, 3
call my_add
my_add:
add eax, ebx
add eax, ‘0’
mov [output], eax
mov byte [output+1], 10
call my_print
ret
44
Outline
•
•
•
•
•
•
•
•
45
Boxes within Boxes
Procedure Definition
call, ret
Saving / Restoring Registers
Argument(s)
Return Value(s)
Global vs. Local Data
Accidental Recursion
Return Value(s)
• How do you return value(s) from assembly procedures?
• Register(s), of course!!
• Example: convert character from lowercase to uppercase
46
mov al, ‘a’
call convert
; argument 1 in al
; convert ‘a’ to ‘A’
; cl now has converted
covert:
mov cl, al
sub cl, 32
; procedure to convert
; copy argument 1
; make return value uppercase
; (‘A’ is 32 less than ‘a’)
; return to caller
ret
mov al, ‘a’;
call convert;
covert:
mov cl, al
sub cl, 32
ret
al
cl
mov al, ‘a’;
call convert;
covert:
mov cl, al
sub cl, 32
ret
al
cl
96 = 0x61 = ‘a’
mov al, ‘a’;
call convert;
covert:
mov cl, al
sub cl, 32
ret
al
cl
96 = 0x61 = ‘a’
mov al, ‘a’;
call convert;
covert:
mov cl, al
sub cl, 32
ret
al
96 = 0x61 = ‘a’
cl
96 = 0x61 = ‘a’
mov al, ‘a’;
call convert;
covert:
mov cl, al
sub cl, 32
ret
al
96 = 0x61 = ‘a’
cl
65 = 0x41 = ‘A’
mov al, ‘a’;
call convert;
covert:
mov cl, al
sub cl, 32
ret
al
96 = 0x61 = ‘a’
cl
65 = 0x41 = ‘A’
now cl has return value ‘A’
Outline
•
•
•
•
•
•
•
•
54
Boxes within Boxes
Procedure Definition
call, ret
Saving / Restoring Registers
Argument(s)
Return Value(s)
Global vs. Local Data
Accidental Recursion
Global vs. Local Data
• Global: can be accessed anywhere in code
• Local: can only be accessed “locally” (e.g., within procedure)
• In x86 assembly, all declared data items are global
• Can declare data items in .text (!!!)
• Appear local, but actually global
55
Examples of Local Data
• Using the stack to temporarily store data in procedures
• Data pushed to stack (during procedure) only visible to that procedure
• Data items declared in external code libraries
• Only visible to external code
• (But there is a mechanism to make global)
56
Outline
•
•
•
•
•
•
•
•
57
Boxes within Boxes
Procedure Definition
call, ret
Saving / Restoring Registers
Argument(s)
Return Value(s)
Global vs. Local Data
Accidental Recursion
Accidental Recursion
• “Uncommon but inevitable bug”
• Watch out for incorrect base case
• Pay attention to instruction => flags
• Will eventually run out of stack space
• Each call pushes 32-bits onto stack (Why?)
• Eventually causes a Segmentation Fault (Why?)
58
Accidental Recursion Example
• “Not so accidental” recursion
call recur;
recur:
call my_print
“LINE”
call recur
ret
59
; 1st instruction in .text
; after _start
; call procedure to print
; make recursive call
; never reached..
Accidental Recursion Example
UNIX> ./a.out
LINE
LINE
stdout in BLUE
LINE
stderr in GREEN
LINE
LINE
... (on and on..)
Segmentation Fault
UNIX>
60
call recur;
recur:
call my_print
call recur
ret
Accidental Recursion Example
UNIX> ./a.out > output.txt
Segmentation Fault
UNIX> head –n 2 output.txt
LINE
LINE
UNIX> wc –l output.txt
2094543 output.txt
61
Accidental Recursion Example
UNIX> ./a.out > output.txt
Segmentation Fault
UNIX> head –n 2 output.txt
LINE
LINE
UNIX> wc –l output.txt
2094543 output.txt
62
> : redirect stdout to a
file named “output.txt”
stderr ignored
Accidental Recursion Example
UNIX> ./a.out > output.txt
Segmentation Fault
UNIX> head –n 2 output.txt
LINE
LINE
UNIX> wc –l output.txt
2094543 output.txt
63
head –n 2 output.txt
:
output top 2 lines of
file output.txt
output.txt contains
“LINE” printed once
per line
Accidental Recursion Example
UNIX> ./a.out > output.txt
Segmentation Fault
UNIX> head –n 2 output.txt
LINE
LINE
UNIX> wc –l output.txt
2094543 output.txt
wc –l output.txt :
count number of lines
in file output.txt
output.txt contains 2,094,543 lines.
recur called 2+ million times!!
64