48 lines
2.8 KiB
ArmAsm
48 lines
2.8 KiB
ArmAsm
# as --32 hello-x86-32.s && ld.gold -m32 -s -n -o hello a.out
|
||
.data # section declaration
|
||
msg:
|
||
.string "All your codebase is belong to us\n" # our dear string
|
||
|
||
len = . - 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.
|
||
|
||
# https://stackoverflow.com/questions/3683144/linux-64-command-line-parameters-in-assembly
|
||
# https://wiki.cdot.senecacollege.ca/wiki/X86_64_Register_and_Instruction_Quick_Start
|
||
square:
|
||
pushl %ebp # Save ebp - this must be restored at end of call
|
||
movl %esp, %ebp # Update base pointer from current stack pointer
|
||
# 8 bytes above ebp is our first parameter
|
||
# (4 bytes above is our return address)
|
||
# In this case, _start is not explictly adding
|
||
# our parameter to the stack as that is being
|
||
# done prior to us being exec'd in the first place
|
||
# There is a good diagram of this in the calling
|
||
# convention section on https://www.cs.virginia.edu/~evans/cs216/guides/x86.html
|
||
movl 8(%ebp), %eax # Move stack memory into eax for multiplication
|
||
imull 8(%ebp), %eax # Do multiplication
|
||
popl %ebp # Restore rbp for return (eax/rax has return val)
|
||
ret # Return
|
||
|
||
_start:
|
||
|
||
# Linux syscalls for 32 bit:
|
||
# https://github.com/torvalds/linux/blob/master/arch/x86/entry/syscalls/syscall_32.tbl
|
||
# write our string to stdout
|
||
movl $4,%eax # system call number (sys_write)
|
||
movl $1,%ebx # first argument: file handle (stdout)
|
||
movl $msg,%ecx # second argument: pointer to message to write
|
||
movl $len,%edx # third argument: message length
|
||
int $0x80 # call kernel and exit
|
||
# argc is stored in (%esp)
|
||
movl (%esp),%edi # See: https://wiki.cdot.senecacollege.ca/wiki/X86_64_Register_and_Instruction_Quick_Start
|
||
# The above instruction is part of the calling convention,
|
||
# so left here, but it's useless/unnecessary and can be removed
|
||
call square # Square our argc, result in %eax
|
||
movl %eax,%ebx # mov %eax to the first syscall argument (exit code)
|
||
movl $1,%eax # system call number (sys_exit)
|
||
int $0x80 # call kernel
|