I am following along with a tutorial online which provides code written in NASM Syntax. The code provided is:
global _start
_start:
sub esp, 4
mov [esp], byte 'H'
mov [esp+1], byte 'e'
mov [esp+2], byte 'y'
mov [esp+3], byte '!'
mov eax, 4 ; sys_write system call
mov ebx, 1 ; stdout file descriptor
mov ecx, esp ; pointer to bytes to write
mov edx, 4 ; number of bytes to write
int 0x80 ; perform system call
mov eax, 1 ; sys_exit system call
mov ebx, 0 ; exit status is 0
int 0x80
I have tried to translate this into AT&T syntax. I have written the following:
.global _start
_start:
sub $4, %esp
movb $'H', (%esp)
movb $'e', 1(%esp)
movb $'y', 2(%esp)
movb $'!', 3(%esp)
mov $4, %eax
mov $1, %ebx
mov %esp, %ecx
mov $4, %edx
int $0x80
mov $1, %eax
mov $0, %ebx
int $0x80
However when I compile and execute this code, I get:
./build.sh: line 35: 1159 Segmentation fault (core dumped) ./$FILE
139
Is my translation from NASM to AT&T correct? And if so, is there something I am missing in terms of being able to read/write from the memory allocated for the Stack? (Permissions etc.)
Build Info:
Building on Arch Linux for a 64-bit system
build.sh script:
function usage {
echo $'\nUsage: ./build.sh -f [filename]\n'
echo $' -f The filename of the source file to be compiled without the file extension.\n'
}
if [ $# -lt 1 ]; then
echo "No input files specified!"
usage
exit 1
fi
while [ $# -gt 0 ]; do
case "$1" in
-f)
shift
FILE=$1
shift
;;
*)
echo "Please use -f to specify the input file!"
usage
exit 1
;;
esac
done
if [ ! -f $FILE.s ]; then
echo "$FILE.s doesn't exist!"
usage
exit 1
fi
gcc -c $FILE.s -o $FILE.o
ld $FILE.o -o $FILE
./$FILE
echo $?
You compiled it as 64 bit code, although int 0x80
is a 32 bit interrupt.
What I used to compile:
as --32 inAssembly.s &&ld -o executable -m elf_i386 a.out
.
as --32 inAssembly.s
makes the gnu assembler assume a 32 bit architecture, emitting a 32-bit objectfile.
ld -o executable -m elf_i386 a.out
invokes the linker, setting the target to elf_i386
and puts the linked file into executable
.