Linux is 32-bit, runs in protected mode, has flat memory model, and uses the ELF format for binaries.
A program can be divided into sections: .text
for your code
(read-only), .data
for your data (read-write),
.bss
for uninitialized data (read-write); there can actually
be a few other standard sections, as well as some user-defined sections, but
there's rare need to use them and they are out of our interest here. A program
must have at least .text
section.
Now we will write our first program. Here is sample code:
section .text ;section declaration ;we must export the entry point to the ELF linker or global _start ;loader. They conventionally recognize _start as their ;entry point. Use ld -e foo to override the default. _start: ;write our string to stdout mov edx,len ;third argument: message length mov ecx,msg ;second argument: pointer to message to write mov ebx,1 ;first argument: file handle (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel ;and exit mov ebx,0 ;first syscall argument: exit code mov eax,1 ;system call number (sys_exit) int 0x80 ;call kernel section .data ;section declaration msg db "Hello, world!",0xa ;our dear string len equ $ - msg ;length of our dear string
.text # section declaration # we must export the entry point to the ELF linker or .global _start # loader. They conventionally recognize _start as their # entry point. Use ld -e foo to override the default. _start: # write our string to stdout movl $len,%edx # third argument: message length movl $msg,%ecx # second argument: pointer to message to write movl $1,%ebx # first argument: file handle (stdout) movl $4,%eax # system call number (sys_write) int $0x80 # call kernel # and exit movl $0,%ebx # first argument: exit code movl $1,%eax # system call number (sys_exit) int $0x80 # call kernel .data # section declaration msg: .ascii "Hello, world!\n" # our dear string len = . - msg # length of our dear string