Computer Architectures
Computer Architectures
Computer Architectures
0x7fffffff ●
The executable file is mapped
(“loaded”) to process address space –
Stack
sections .data and .text (note: LMA !=
VMA for some special cases)
●
Uninitialized data area (.bss – block
Dynamic memory starting by symbol) is reserved and
alloc. – heap zeroed for C programs
Uninitialized data ●
Stack pointer is set and control is
.bss passed to the function _start
Initialized data ●
Dynamic memory is usually allocated
.data
above _end symbol pointing after .bss
Program code
.text
0x00000000
AE0B36APO Computer Architectures 3
Process address space (32-bit x86 Linux)
Based on:
Anatomy of a Program in Memory
http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory
AE0B36APO Computer Architectures 4
Steps processed during subroutine call
● Calling routine/program (caller) calculates the values of the parameters
● Caller prepares for overwrite of registers which ABI specifies as clobberable
(can be modified by callee) storing values which are still neded
● Parameters values are placed in registers and or on stack according to used
ABI calling convention
● Control is transferred to the first subroutine instruction while return address is
saved on stack or stored in dedicated register
● Subroutine saves previous values of registers, which are to be used and are
specified as callee saved/non-clobberable
● Space for local variables is allocated on stack
● The body of subroutine is executed
● The function result is placed to register(s) defined by calling convention
● Values of callee saved/non-clobberable registers are restored
● Return from subroutine instruction is executed, it can release stack space used
for parameters but it is usually caller duty to adjust stack to free parameters
Caller/jal stores return address into ra (reg $31) and transfers control to the
callee/subroutine first instruction. Call returns by jump to return address (jr $ra).
AE0B36APO Computer Architectures 9
Code example
leaf_fun:
addi $sp, $sp, -4
sw $s0, 0($sp) Save $s0 on stack
main: mult:
jal mult …
Laftercall2: …
fact:
addi $sp, $sp, -8 # adjust stack for 2 items
sw $ra, 4($sp) # save return address
sw $a0, 0($sp) # save argument
slti $t0, $a0, 1 # test for n < 1
beq $t0, $zero, L1
addi $v0, $zero, 1 # if so, result is 1
addi $sp, $sp, 8 # pop 2 items from stack
jr $ra # and return
L1: addi $a0, $a0, -1 # else decrement n
jal fact # recursive call
lw $a0, 0($sp) # restore original n
lw $ra, 4($sp) # and return address
addi $sp, $sp, 8 # pop 2 items from stack
mul $v0, $a0, $v0 # multiply to get result
jr $ra # and return
#include <stdio.h> f:
pushl %ebp
int f(int x) movl %esp, %ebp
{ movl 8(%ebp), %eax
return x; leave
} ret
…
g
int g() $ESP Input[0]
{ Addr of input
char input[30]; Old $EIP
$EBP and $ESP f
f(input); Old $EBP
}
AE0B36APO Computer Architectures 22
x86: Example with More Arguments
int simple(int a, int b, int c, int d, int e, int f){
return a-f;
}
int main(){
int x;
x=simple(1, 2, 3, 4, 5, 6);
return 0;
}
_main:
pushl %ebp ebp saved on stack, push modifies esp
_simple: movl %esp, %ebp esp to ebp
pushl %ebp andl $-16, %esp allign stack to 16-bytes
movl %esp, %ebp subl $48, %esp esp = esp – 48 (allocate space)
movl 28(%ebp),%eax call ___main
movl 8(%ebp),%edx movl $6, 20(%esp) the last argument
movl %edx, %ecx movl $5, 16(%esp) the fifth argument
subl %eax, %ecx movl $4, 12(%esp) ...
movl %ecx, %eax movl $3, 8(%esp) ...
popl %ebp movl $2, 4(%esp) ...
ret movl $1, 0(%esp) the first argument
call _simple call the function
movl %eax, 44(%esp) store result to global x = simple(…);
movl $0, %eax return 0;
leave
ret
AE0B36APO Computer Architectures 23
x86 calling convention for 64-bit mode (for Linux)
● Original 32-bit calling convention is expensive, too many main memory
(stack) accesses
● 64-bit registers $RAX, $RBX, $RCX, $RDX, $RSI, $RDI, $RBP, $RSP,
$R8 … R15 and many multimedia registers
● AMD64 ABI/calling convention places up to the first 6 integral data type
parameters in $RDI, $RSI, $RDX, $RCX, $R8 and $R9 registers
● The first 8 double and float data type parameters in XMM0-7
● Return/function result value in $RAX
● Stack is always 16-byte aligned when a call instruction is executed
● If calling function without prototype or function with variable arguments
count (va_arg/...) then $RAX has to be set to number of parameters
passed in registers (never use va_arg twice without va_copy)
Other ...user task
User space process...
processes continues
read device file are
scheduled return
System call... ... finalization
User Service
Program Routine
Wrapper System
Routine Call
(Glibc) Handler
fread(c,1,30.fil
ename)
Load
Push Argument
Register
EAX=__NR_R SAVE_ALL
EAD Check limit
INT 0x80 of EAX
syscall_tab[ Check Destination
EAX] Retrieve Data
Copy Data
Return
RESTORE_A
LL
iret
Check Error
return
Return
#include <asm/unistd.h>
#include <asm/asm.h> # close(fd);
#include <sys/syscall.h> move a0,s0
li v0,SYS_close
#define O_RDWR 02 syscall
.set noreorder
LEAF(main) quit:
# fd = open("/dev/tty1", O_RDWR, 0); li a0,0
la a0,tty li v0,SYS_exit
li a1,O_RDWR syscall
li a2,0
li v0,SYS_open j quit
syscall nop
bnez a3,quit
move s0,v0 # delay slot END(main)
# write(fd, "hello, world.\n", 14);
move a0,s0 .data
la a1,hello tty: .asciz "/dev/tty1"
li a2,14 hello: .ascii "Hello, world.\n"
li v0,SYS_write
syscall