In the context of a compiler construction project, I used to be able to compile "ia32" code like this before:
$ gcc -m32 -ofoo foo.s
with foo.s looking like:
.file "tiger-runtime.c"
.text
.globl tc_init_array
.type tc_init_array, #function
tc_init_array:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $40, %esp
movl 8(%ebp), %eax
sall $2, %eax
movl %eax, (%esp)
call malloc
movl %eax, -16(%ebp)
movl $0, -12(%ebp)
jmp .L2
Now that I moved to Yosemite and the latest version of Xcode, I get:
$ gcc-mp-5 -m32 -oadd-ia32 add-ia32.s
tiger-runtime.c:4:Unknown pseudo-op: .type
tiger-runtime.c:4:Rest of line ignored. 1st junk character valued 116 (t).
tiger-runtime.c:7:Unknown pseudo-op: .cfi_startproc
tiger-runtime.c:9:Unknown pseudo-op: .cfi_def_cfa_offset
tiger-runtime.c:9:Rest of line ignored. 1st junk character valued 56 (8).
tiger-runtime.c:10:Unknown pseudo-op: .cfi_offset
tiger-runtime.c:10:Rest of line ignored. 1st junk character valued 53 (5).
tiger-runtime.c:12:Unknown pseudo-op: .cfi_def_cfa_register
and more errors like this. This question has been asked many times, but none of the answers I've seen so far work on Yosemite (e.g., mac OSX Unknown pseudo-op: .type, I'm learning x86 assembly on OS X 10.6, how do I compile?). In particular, even if I use GCC (say GCC 5 via MacPorts) as a compiler driver, it appears to use /usr/bin/as, not its own assembler.
I have installed several versions of GCC/Clang/Binutils (via MacPorts) to try to find the right assembly, but without success. At best, I get:
$ /opt/local/i386-elf/bin/as add-ia32.s -o add-ia32.o
$ /opt/local/i386-elf/bin/ld add-ia32.o -o add-ia32
/opt/local/i386-elf/bin/ld: warning: cannot find entry symbol _start; defaulting to 00000000
add-ia32.o: In function `tc_init_array':
tiger-runtime.c:(.text+0x10): undefined reference to `malloc'
add-ia32.o: In function `tc_malloc':
tiger-runtime.c:(.text+0x54): undefined reference to `malloc'
tiger-runtime.c:(.text+0x68): undefined reference to `stderr'
tiger-runtime.c:(.text+0x88): undefined reference to `fwrite'
tiger-runtime.c:(.text+0x94): undefined reference to `exit'
I guess I'm not too far from completion, yet the convention for the main function seems to differ, and it doesn't find the libc (-lc does not help).
A full version of the assembly file that used to work properly is available here: http://pastebin.com/Xq8DTmf6. Thanks in advance.
Related
I'm learning the basics of x86 via this free book.
Keep in mind this is specific to macOS x86 compared to Linux x86.
Its made for GNU Linux, so I have to change some of the code which is probably where I went wrong. I took this code snippet:
.section .data
.section .text
.globl _start
_start:
movl $1, %eax
movl $0, %ebx
int $0x80
After a bit of googling about x86 on macOS I turned that bit of code into this:
.data
.text
.globl _main
_main:
movl $1, %eax
movl $0, %ebx
int $0x80
I compiled this using gcc test.s which compiles it into a.out. When trying to run it using ./a.out I get the error [1] 17301 illegal hardware instruction ./a.out.
Any help is appreciated, thanks!
#Jester helped me out. You can view the comment on my question, but basically call convention is different for macOS. I found this resource which helped me out.
I wrote the code below. I want to compile it using gcc on mac OS X,
but I get a message saying "PIE disabled. Absolute addressing" when I run gcc.
I googled it, but cannot find a solution.
Please advise.
hello.s file:
.data
hello: .string "Hello World!\n"
.text
.globl _main
_main:
push %rbp
mov %rsp, %rbp
movabs $hello, %rdi
call _printf
leave
ret
The error:
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in
code signed PIE, but used in _main from /var/folders/xs/4z9kr_n93111fhv9_j1dd9gw0000gn/T/ex2_64-369300.o.
To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
Looks like there are a couple solutions:
Link with -Wl,-no_pie:
clang -o hello hello.s -Wl,-no_pie
Don't use absolute addressing.
.data
hello: .string "Hello World!\n"
.text
.globl _main
_main:
push %rbp
mov %rsp, %rbp
lea hello(%rip), %rdi
mov $0, %rax
call _printf
leave
ret
Then you can compile and run:
host % clang -o hello hello.s
host % ./hello
Hello World!
The bit about zeroing out al is mentioned in section 3.5.7 of System V Application Binary Interface. Here's the relevant excerpt:
When a function taking variable-arguments is called, %al must be set
to the total num- ber of floating point parameters passed to the
function in vector registers.
In your case this is zero. You are passing in zero floating point parameters.
I've been trying to get familiar with assembly on mac, and from what I can tell, the documentation is really sparse, and most books on the subject are for windows or linux. I thought I would be able to translate from linux to mac pretty easily, however this (linux)
.file "simple.c"
.text
.globl simple
.type simple, #function
simple:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx
movl 12(%ebp), %eax
addl (%edx), %eax
movl %eax, (%edx)
popl %ebp
ret
.size simple, .-simple
.ident "GCC: (Ubuntu 4.3.2-1ubuntu11) 4.3.2"
.section .note.GNU-stack,"",#progbits
seems pretty different from this (mac)
.section __TEXT,__text,regular,pure_instructions
.globl _simple
.align 4, 0x90
_simple: ## #simple
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
addl (%rdi), %esi
movl %esi, (%rdi)
movl %esi, %eax
popq %rbp
ret
.cfi_endproc
.subsections_via_symbols
The "normal" (for lack of a better word) instructions and registers such as pushq %rbp don't worry me. But the "weird" ones like .cfi_startproc and Ltmp2: which are smack dab in the middle of the machine instructions don't make any sense.
I have no idea where to go to find out what these are and what they mean. I'm about to pull my hair out as I've been trying to find a good resource for beginners for months. Any suggestions?
To begin with, you're comparing 32-bit x86 assembly with 64-bit x86-64. While the OS X Mach-O ABI supports 32-bit IA32, I suspect you want the x86-64 SysV ABI. (Thankfully, the x86-64.org site seems to be up again). The Mach-O x86-64 model is essentially a variant of the ELF / SysV ABI, so the differences are relatively minor for user-space code, even with different assemblers.
The .cfi directives are DWARF debugging directives that you don't strictly need for assembly - they are used for call frame information, etc. Here are some minimal examples:
ELF x64-64 assembler:
.text
.p2align 4
.globl my_function
.type my_function,#function
my_function:
...
.L__some_address:
.size my_function,[.-my_function]
Mach-O x86-64 assembler:
.text
.p2align 4
.globl _my_function
_my_function:
...
L__some_address:
Short of writing an asm tutorial, the main differences between the assemblers are: leading underscores for Mach-O functions names, .L vs L for labels (destinations). The assembler with OS X understands the '.p2align' directive. .align 4, 0x90 essentially does the same thing.
Not all the directives in compiler-generated code are essential for the assembler to generate valid object code. They are required to generate stack frame (debugging) and exception handling data. Refer to the links for more information.
Obviously the Linux code is 32-bit Linux code. Note that 64-bit Linux can run both 32- and 64-bit code!
The Mac code is definitely 64-bit code.
This is the main difference.
The ".cfi_xxx" lines are only information used for the Mac specific file format.
I've run into an issue after following this tutorial - https://www.youtube.com/watch?v=RvvRO_gWYIg
A few possible issues:
it looks like the processor architecture and operating system may differ quite heavily from the one I'm working on. In the video it seems to be an i386 linux box, and I'm working on an x64 OSX machine.
When commenting out the helloWorldStr reference, it starts working again.
Assembling on a 64 bit machine with 32 bit instructions
Posted below is the broken code, any help would be greatly appreciated!
# Hello World Program:
.data
HelloWorldStr:
.ascii "Hello World"
.text
.globl start
start:
# Load all the arguments for write():
# write(output, string, string_size)
movl $4, %eax # Load write()
movl $1, %ebx # Arg Output of write() :: STDOUT
movl $HelloWorldStr, %ecx # Referencing the Memory Loc. of the String
movl $11, %edx # Byte length of the String "Hello World"
int $0x80
# Call Exit:
movl $1, %eax
movl $0, %ebx
int $0x80
Also, here are some errors that have arisen:
Undefined symbols for architecture x86_64:
"_main", referenced from:
start in crt1.10.6.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
So I changed _start to _main and then that passed on to the next error:
gcc HelloWorldProgram.s -m32
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in _main from /var/folders/8t/7639_vls58lgd1nnwx4dpbh40000gn/T//cc3wDW8K.o. To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
You might check out this answer from a previous question. The user was also using Mac OS X and following a similar tutorial that was taught using Linux.
Here's an example hello world generated with a slightly newer compiler than the linked to answer (it's still quite similar).
hello.s
.section __TEXT,__cstring,cstring_literals
L_.str:
.asciz "Hello world!\n"
.section __TEXT,__text,regular,pure_instructions
.globl _main
.align 4, 0x90
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $L_.str, (%esp)
call _puts
xorl %eax, %eax
addl $8, %esp
popl %ebp
ret
.subsections_via_symbols
I'm trying to follow the book Professional Asssembly Language on Mac OS X Montain Lion.
On google I found a port for Mac OS X at the following url: Assembly on MacOS X
Created the file with Vim and compiled it with GAS:
as -g -arch i386 -o cpuid.o cpuid.s
Linked the code using gcc:
gcc -m32 -arch i386 -o cpuid cpuid.o
The resulting executable cpuid, runs without errors but if I try to debug it with gdb at the end it says Program exited with code 044 instead of Program exited normally.
Trying to find a way to make it exit correctly I've created an hello world example in C and generated assembly code it with:
gcc -Wall -03 -m32 -fno-PIC hello_pf.c -S -o hello_pf.s
The resulting assembly code is bellow:
.section __TEXT,__text,regular,pure_instructions
.globl _main
.align 4, 0x90
_main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
leal L_.str, %eax
movl %eax, (%esp)
call _puts
movl $0, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
addl $24, %esp
popl %ebp
ret
.section __TEXT,__cstring,cstring_literals
L_.str:
.asciz "Hello world!\n"
.subsections_via_symbols
Can someone provide any help regarding this issue?
How can I make a working version of cpuid from the link provided above using IA-32 mac ox s assembly?
Where can I look for a detailed description of stack align problem in Mac OS X? I've read what's on Apple site but for a beginner is not very helpful.
What are for the instructions after call _puts from the above sample code?
How does calling libc functions from assembly really works? Any good detailed articles on this topic?
Thank you!
First you need to understand the register usage in the calling conventions, a good place for that is
http://www.agner.org/optimize/calling_conventions.pdf
You will find that on Mac OS X 64-bit the return value for a function returning an "int" - such as main() - is in %rax. You seem to want to use a 32-bit executable, in which case the return value is in %eax. One convenient way to zero out a register is to XOR it with itself, so you should add this to the end of your routine:
xorl %eax,%eax
That'll set %eax to zero, and that will be your exit code.