GAS .code16

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

GAS .code16

Post 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)
Every good solution is obvious once you've found it.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GAS .code16

Post 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?
Every good solution is obvious once you've found it.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GAS .code16

Post 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
Every good solution is obvious once you've found it.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GAS .code16

Post 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?
Every good solution is obvious once you've found it.
AR

Re:GAS .code16

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:GAS .code16

Post 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
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.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GAS .code16

Post 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.
Every good solution is obvious once you've found it.
AR

Re:GAS .code16

Post 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]
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GAS .code16

Post 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?
Every good solution is obvious once you've found it.
AR

Re:GAS .code16

Post 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.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GAS .code16

Post 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.
Every good solution is obvious once you've found it.
AR

Re:GAS .code16

Post by AR »

The GNU nuts need some help with their versioning, that's just confusing.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GAS .code16

Post 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? 8)
Every good solution is obvious once you've found it.
AR

Re:GAS .code16

Post 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.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GAS .code16

Post 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. ;)
Every good solution is obvious once you've found it.
Post Reply