64-bit |
32-bit |
16-bit |
|
First Year |
2003 (AMD Athlon64) |
1985 (Intel 386) |
1978 (Intel 8086/8088) |
Typical OS |
Vista 64 |
Windows 95 through XP |
Windows 3.1, MS DOS, PC boot sector |
Pointers |
64-bit (8 byte QWORD) |
32-bit (4 byte DWORD) |
16-bit (2 byte WORD) "near" pointer; add another 16-bit segment number for a "far" pointer |
Registers |
rax, r8-r15, etc. |
scratch: eax, ecx, edx preserved: ebx, esp, ebp, esi, edi |
ax, bx, cx, dx, sp, bp, si, di segment registers: ss, ds, cs, es |
Stack |
Must be 16-byte aligned |
Only 4-byte aligned (watch out for SSE!) |
No alignment required, but usually 2-byte aligned |
Parameters |
In rdi, rsi, etc |
On stack (in most call conventions) |
Totally up to you. |
SSE |
Yes, xmm0-xmm15 |
Probably, but only xmm0-xmm7 |
No |
mov eax,17To call a function like print_int with the parameter 13, in 32-bit mode we need to push it onto the stack:
ret
push 13 ; print_int's first parameterThe first parameter is always on top of the stack, at [esp+4]. The second parameter needs to be deeper in the stack, so curiously you must push the leftmost parameter last!
extern print_int
call print_int
pop eax ; <- clean up stack before returning
ret
push 1 ; number of floats to print (second argument)Other than that, 32-bit assembly is pretty nearly identical to 64-bit assembly!
push myFloat ; address of our float (first argument)
extern farray_print
call farray_print
add esp,8 ; Clean up stack
ret ; Done with function
myFloat: dd 1.234
push rbx ; <- we'll be using ebx below, and it's a saved register (hallelujah!)
; System calls are listed in "asm/unistd.h"
mov rax,4 ; the system call number of "write".
mov rbx,1 ; first parameter: 1, the stdout file descriptor
mov rcx,myStr ; data to write
mov rdx,3 ; bytes to write
int 0x80 ; Issue the system call
pop rbx ; <- restore ebx to its old value
ret
section .data
myStr:
db "Yo",0xa