Page 1 of 2
GAS .code16
Posted: Wed Jul 13, 2005 10:18 pm
by Solar
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:
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)
Re:GAS .code16
Posted: Wed Jul 13, 2005 10:18 pm
by Solar
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?
Re:GAS .code16
Posted: Wed Jul 13, 2005 10:20 pm
by Solar
Whereas came this reply:
No, I'm not that incompetent, here's a code snippet:
Code: Select all
.text
.code16
ljmp $0, $start
start:
movw var1, %eax
jmp end
var1: .word 0x4A4A
end:
1:
jmp 1b
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.o
Output from the NASM Disassembler:
Code: 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
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 use
Re:GAS .code16
Posted: Wed Jul 13, 2005 10:25 pm
by Solar
Above code snippet gives me
Code: Select all
test.S: Assembler messages:
test.S:7: Warning: using `%ax' instead of `%eax' due to `w' suffix
and a disassembly of
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
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?
Re:GAS .code16
Posted: Wed Jul 13, 2005 10:42 pm
by AR
Objdump is lying, try a hex editor, look for 66 and 67 (o32, addr32 respectively).
Try the NASM disassembler, it tells a different story.
Re:GAS .code16
Posted: Wed Jul 13, 2005 10:43 pm
by Brendan
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
Re:GAS .code16
Posted: Thu Jul 14, 2005 12:17 am
by Solar
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:
Code: Select all
0000000 05ea 007c a100 7c0a 02eb 4a4a feeb
ndisasm output:
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
Seems like there's a problem with either the version used, or some settings have been borked, but I can't reproduce the behaviour.
Re:GAS .code16
Posted: Thu Jul 14, 2005 12:52 am
by AR
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
Posted: Thu Jul 14, 2005 2:19 am
by Solar
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?
Re:GAS .code16
Posted: Thu Jul 14, 2005 2:56 pm
by AR
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.
Re:GAS .code16
Posted: Thu Jul 14, 2005 9:50 pm
by Solar
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:
Changes in 2.10:
(...)
* Full 16-bit mode support for i386.
Re:GAS .code16
Posted: Thu Jul 14, 2005 10:00 pm
by AR
The GNU nuts need some help with their versioning, that's just confusing.
Re:GAS .code16
Posted: Thu Jul 14, 2005 11:43 pm
by Solar
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?
Re:GAS .code16
Posted: Fri Jul 15, 2005 12:51 am
by AR
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
Posted: Fri Jul 15, 2005 12:54 am
by Solar
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.