output format

Hi, i got some problems where I can't find a solution for.

Let's say I wrote something like this:
[code]global kernel
mov ax, 0xb800
mov ds, ax
mov ax, 0
mov si, ax
mov al, 'x'
mov byte [ds:si], al
loop1: jmp loop1[/code]
This put the letter 'x' directly in the video memory.
So if I assemble it in a flat binary, put it on a floppy and boot from it, it works perfectly.

Now the problem is, if I want to combine my assembly object file with a object file from let's say a 'c' program, I can't use the flat binary format.
So i have to use the elf format.
So if I use "nasm kernel.asm -f elf -o kernel.o"
and dissasmble the file and check the specific code it looks like this:

[code]00000000 66B800B88ED8 mov eax,0xd88eb800
00000006 66B800006689 mov eax,0x89660000
0000000C C6 db 0xC6
0000000D B078 mov al,0x78
0000000F 3E678804C3 mov [dword ds:ebx+rax*8],al
00000014 EBFE jmp short 0x14
You see that my "[code]mov ds, ax
mov si, ax[/code]
aren't there anymore. And as you could think the code doesn't work anymore.

So is it possible to link assembly with other files using a flat binary?
Or is it possible to fix the problem of my disapearing code?
btw: if I use inline assembly in gcc and write the same code and compile it, the exact code dissapears.
So its not only the problem of nasm, also of gcc.

I hope someone understands me? And knows an answer?

If you want more info, just tell me :) thanks..


  • For instance:
    MOV SI, AX -> 89C6
    MOV DS, AX -> 8ED8
    MOV AX, B800 -> B800B8
    00000000 xxB800B88ED8 mov eax,0xd88eb800
    00000006 66B800006689 mov eax,0x89660000
    0000000C C6 db 0xC6
    That code is there...
    I don't know much about 32-bit
    instruction format, but is your GCC generating
    32-bit code, it looks alot like 16-bit though?

    The bootup process is called bootstrapping
    because it is like strapping up a pair of
    boots, one part of the system brings up
    other usually larger parts of the system into

  • Basically you're mixing 16-bit and 32-bit code.

    For flat binaries, Fasm generates 16-bit code by default,
    but switches to 32-bit if the Elf format is specified. GCC assembles to 32-bit code by default.

    Now, notice the prefix 66 in front of the instructions. This prefix changes the operand size. In 16-bit mode, the prefix tells the processor to use the 32-bit eax instead of the default 16-bit ax. In 32-bit mode, it's the other way around.

    When compiling to the 32-bit Elf format, Fasm inserts the prefix, because the operand is ax. However, the disassembler is configured to always assume that it sees 16-bit code, so it thinks the prefix means to take eax instead of ax. In that case, since the operands are both 4 bytes instead of 2, the disassembler reads a larger immediate value of 0xd88eb800 instead of 0xb800. The 0xd88e part is the opcode for "mov ds, ax", but now it is considered part of the preceeding instruction and gets lost.

    I hope this makes sense.

    Also, in user mode Linux you won't be able to write directly to video memory like you could in a bootstrap program, so it won't work anyway :(
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!