Hi,
I wrote some line of code in asm in NASM:
mov bx,ax
I converted to binary code using: nasm -o test.bin test.s
using ndisasm test.bin, the resulting binary code is: 89C3, it says in ndisasm mov bx ax
(00000000 89C3 mov bx,ax)
and I wrote the exact line of code in GAS syntax:
movw %ax,%bx
I converted to binary code using: gas -o test2.o test2.s && ld --oformat binary -s -o test2.bin test2.s
using ndisasm test2.bin, the resulting binary code is 6689C3 (that is bad), it says in ndisasm mov ebx eax
(00000000 6689C3 mov ebx,eax)
What's happening?? Why GAS and LD are making bad machine code?
Please, I need help...
Problem with GAS assembler and LD linker
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Problem with GAS assembler and LD linker
There are several things in play here
- GAS has its own syntax, which is not the intel syntax. It throws around weird symbols, invents different names for opcodes, and switches operands
- GAS is built for one platform. It will by default emit code for a unix machine, so if you run 32 bit linux, GAS will make code to run in 32 bits mode. If you run 64-bit linux, GAS will emit 64-bit code.
NASM on the other hand is older, and while capable of emitting both 16, 32 and 64 bit code from the same binary, it defaults to 16-bit. You are making a flat binary, which is often used to make DOS (=16 bit) .com files.
- The processor has 16 and 32 (and 64) bits modes. Thee opcodes are shared, but the register sizes are not to save space. Instead, they added prefixes (opcodes 66 and 67) which tell the CPU to swap the instruction from the current mode to the other mode (32->16 or 16->32) GAS needs to execute a 16-bit instruction in 32-bit mode, so it adds the prefix. When a 16-bit disassembler sees that prefix, it will think the next instruction is 32-bits.
So when you next try to interpret 32-bits code as if it were 16-bits code, the result will be off.
- GAS has its own syntax, which is not the intel syntax. It throws around weird symbols, invents different names for opcodes, and switches operands
- GAS is built for one platform. It will by default emit code for a unix machine, so if you run 32 bit linux, GAS will make code to run in 32 bits mode. If you run 64-bit linux, GAS will emit 64-bit code.
NASM on the other hand is older, and while capable of emitting both 16, 32 and 64 bit code from the same binary, it defaults to 16-bit. You are making a flat binary, which is often used to make DOS (=16 bit) .com files.
- The processor has 16 and 32 (and 64) bits modes. Thee opcodes are shared, but the register sizes are not to save space. Instead, they added prefixes (opcodes 66 and 67) which tell the CPU to swap the instruction from the current mode to the other mode (32->16 or 16->32) GAS needs to execute a 16-bit instruction in 32-bit mode, so it adds the prefix. When a 16-bit disassembler sees that prefix, it will think the next instruction is 32-bits.
So when you next try to interpret 32-bits code as if it were 16-bits code, the result will be off.
Re: Problem with GAS assembler and LD linker
Add ".code16" at the beginning of your code.stevencrc wrote: movw %ax,%bx
...
(00000000 6689C3 mov ebx,eax)
Code: Select all
.code16
movw %ax,%bx
"Open source seems to embrace the dark side of human nature." - Ville Turjanmaa
Re: Problem with GAS assembler and LD linker
When assembling to BIN files.berkus wrote:Exactly, gas is by default in 32-bit code, while nasm is using good ole 16-bit as default.
Re: Problem with GAS assembler and LD linker
Thanks for all, was the 32 bit code generated by GAS, I fixed adding .code16.
Thanks for all you are great!!
Thanks for all you are great!!