GAS is not very useful for writing bootsectors with as it insists on prefixing every memory access and jump/call with o32, this requires an additional 3 bytes that are unnecessary (1 for the prefix, 2 for 32bit address) which makes it hard to fit all the required code into the 512byte bootsector. I don't know whether this is just because the developers didn't think it was necessary or because LD lacks the ability to relocate 16bit addresses, in either case you will be better off just using NASM / FASM / YASM / whatever for this. GAS is otherwise ok for 16bit code provided you don't have space concerns. (Note that this was observed with an ELF Cross Compiler, an a.out cross compiler might not have this problem)
GAS .code16
GAS .code16
202.7.166.* wrote to the OS-FAQ about the inability of GNU as to produce efficient RealMode code. As somewhat of a discussion ensued, I decided to drag it into the forum, both because the Wiki isn't the place for discussion and to get it to the attention of a wider audience:
Every good solution is obvious once you've found it.
Re:GAS .code16
I disagree however. I followed the BabyStep tutorial halfway through using GAS, and had no such problems. Could it be that the author forgot to set .code16, still wrote movl or some such?
Every good solution is obvious once you've found it.
Re:GAS .code16
Whereas came this reply:
No, I'm not that incompetent, here's a code snippet:
Something that is also particularly interesting: movw %ss:(%sp), %ax refuses to assemble (Quote: "Error: base/index register must be 32 bit register" - solution is to use %esp). Built with: gcc -o Test.o -c test.S; ld -o Test.bin --oformat binary --Ttext 0x7C00 Test.oCode: Select all
.text .code16 ljmp $0, $start start: movw var1, %eax jmp end var1: .word 0x4A4A end: 1: jmp 1b
Output from the NASM Disassembler:
And contradictory to the ".code16" comment, it actually produces BETTER 16bit code in .code32 since the instructions have the same opcodes but it doesn't bother prefixing, however it creates a mess from the 2 NULL bytes inbetween every instruction. If your version of GAS doesn't make such a mess of it then please enlighten me to what configuration settings to useCode: Select all
00000000 66EA087C00000000 jmp dword 0x0:0x7c08 00000008 67A1117C0000 mov ax,[dword 0x7c11] 0000000E 66EB02 o32 jmp short 0x13 00000011 4A dec dx 00000012 4A dec dx 00000013 66EBFD o32 jmp short 0x13
Every good solution is obvious once you've found it.
Re:GAS .code16
Above code snippet gives me
and a disassembly of
on a plain Linux system (GNU assembler version 2.15.92.0.2 (i686-pc-linux-gnu) using BFD version 2.15.92.0.2 20040927).
So there's still something unclear here. I will try this with a crosscompiler when I find the time (to really have the same environment), but I don't think that will help. What version of binutils are you using?
Perhaps someone can comment?
Code: Select all
test.S: Assembler messages:
test.S:7: Warning: using `%ax' instead of `%eax' due to `w' suffix
Code: Select all
test: file format binary
Disassembly of section .data:
0000000000000000 <.data>:
0: ea 05 7c 00 00 ljmp $0x0,$0x7c05
5: a1 0a 7c mov 0x7c0a,%ax
8: eb 02 jmp 0xc
a: 4a dec %dx
b: 4a dec %dx
c: eb fe jmp 0xc
So there's still something unclear here. I will try this with a crosscompiler when I find the time (to really have the same environment), but I don't think that will help. What version of binutils are you using?
Perhaps someone can comment?
Every good solution is obvious once you've found it.
Re:GAS .code16
Objdump is lying, try a hex editor, look for 66 and 67 (o32, addr32 respectively).
Try the NASM disassembler, it tells a different story.
Try the NASM disassembler, it tells a different story.
Re:GAS .code16
Hi,
I believe the correct tools for 16 bit assembly (in the GNU/*nix world) is A86 and LD86, part of the "bin86" package:
http://www.faqs.org/docs/linux_scratch/ ... bin86.html
Cheers,
Brendan
I believe the correct tools for 16 bit assembly (in the GNU/*nix world) is A86 and LD86, part of the "bin86" package:
http://www.faqs.org/docs/linux_scratch/ ... bin86.html
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:GAS .code16
Edit: Cooled down a bit and edited the rant (sorry). But I'd rather we stop the "incompetent" and "lying" stuff.
The hexdump corresponding to the disassembly above is:
ndisasm output:
Seems like there's a problem with either the version used, or some settings have been borked, but I can't reproduce the behaviour.
The hexdump corresponding to the disassembly above is:
Code: Select all
0000000 05ea 007c a100 7c0a 02eb 4a4a feeb
Code: Select all
00000000 EA057C0000 jmp 0x0:0x7c05
00000005 A10A7C mov ax,[0x7c0a]
00000008 EB02 jmp short 0xc
0000000A 4A dec dx
0000000B 4A dec dx
0000000C EBFE jmp short 0xc
Every good solution is obvious once you've found it.
Re:GAS .code16
I don't know what's wrong with the compiler, (my objdump didn't show the o32/addr32 prefixes in the dump, but they are in the hex dump and disassembly), it's a straightforward i686-elf cross compiler, the only other thing I built in is disable-nls. I have no idea why it's doing this, unless it is just an adverse reaction to Cygwin.
[tt]66 ea 08 7c 00 00 00 00 67 a1 11 7c 00 00 66 eb 02 4a 4a 66 eb fd[/tt]
Re:GAS .code16
Must be; I can't reproduce it even with a i586-elf cross-compiler I had built under Linux. But I really can't imagine how the build environment could affect the assembler that way.
What version is your binutils?
What version is your binutils?
Every good solution is obvious once you've found it.
Re:GAS .code16
GCC 4.0.0
Binutils 2.9.1
Edit: Sorry about my acidity in the Wiki entry, I'd wasted a lot of time on this (wrote an entire bootsector, code wouldn't fit, tried to diagnose and eventually found the o32 problem then had to rewrite in NASM) and didn't re-read it enough to take off the sharp edges.
Binutils 2.9.1
Edit: Sorry about my acidity in the Wiki entry, I'd wasted a lot of time on this (wrote an entire bootsector, code wouldn't fit, tried to diagnose and eventually found the o32 problem then had to rewrite in NASM) and didn't re-read it enough to take off the sharp edges.
Re:GAS .code16
binutils 2.9.1? That is ancient! Why do you use a 1998 binutils with a 2005 GCC? The current version is 2.16.1!
Anyway, I think we can put the matter to rest. Quoting from the CHANGES file:
Anyway, I think we can put the matter to rest. Quoting from the CHANGES file:
Changes in 2.10:
(...)
* Full 16-bit mode support for i386.
Every good solution is obvious once you've found it.
Re:GAS .code16
Ah, I see... sorting alphanumerically, huh?
Well, the GCC Cross-Compiler tutorial you seem to have used sais "tested with binutils 2.14 and 2.15"...
Anyway, this way of versioning things is pretty standard, not only in the Church of St. Gnucius. To the contrary, I would consider leading zeroes (the only possible alternative) to be the height of bad manners. Not to mention that you would get into trouble should your minor version exceed your foresight ("we released 1.01 through 1.99, now what...?").
Or do you suggest binutils 2005?
Well, the GCC Cross-Compiler tutorial you seem to have used sais "tested with binutils 2.14 and 2.15"...
Anyway, this way of versioning things is pretty standard, not only in the Church of St. Gnucius. To the contrary, I would consider leading zeroes (the only possible alternative) to be the height of bad manners. Not to mention that you would get into trouble should your minor version exceed your foresight ("we released 1.01 through 1.99, now what...?").
Or do you suggest binutils 2005?
Every good solution is obvious once you've found it.
Re:GAS .code16
Why not? They already use that sometimes (eg. 20050211 for whatever version was released on 11th Feburary 2005), certainly be easier to understand.
Re:GAS .code16
Version numbers are shorter, easier to take in at a glance, and provide additional information about severty of changes between versions.
But we very successfully avoided getting into a Intel vs. AT&T flamewar, so let's not get into one about versioning systems.
But we very successfully avoided getting into a Intel vs. AT&T flamewar, so let's not get into one about versioning systems.
Every good solution is obvious once you've found it.