Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intel Assembly ljmp syntax from AT&T syntax

I am trying to convert the xv6 boot code from At&t syntax to Intel syntax and I have a problem with the ljmp instruction. I am trying to learn the boot process of Intel computers and I am not particularly strong with Intel assembly.

The original AT&T syntax is ljmp $0x8, $start32.

Minimal example:

.code16
   jmp 0x8:start32          # won't assemble

.code32
start32:
   nop

Using as -32 -msyntax=intel -mnaked-reg foo.s with GNU Binutils 2.35.1 produces
Error: junk ':start32' after expression for the far jmp line.

I am using GNU as, and gcc tools.
There might also be other problems with the assembly such as the gdtdesc and gdt.

The full code ported to Intel syntax is:

# Start the first CPU: switch to 32-bit protectied mode, jump into C.
# The BIOS loads this code from the first sector of the hard disk into
# memory at physical address 0x7c00 and starts executing in real mode
# with cs = 0 and ip = 7c00.
.code16
.global start
start:
    # Disable interrupts.
    cli

    # Zero data segment registers DS, ES, and SS.
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax

seta20.1:
    # Wait for not busy.
    in al, 0x64
    test al, 0x2
    jnz seta20.1

    # 0xd1 -> port 0x64
    mov al, 0xd1
    out 0x64, al

seta20.2:
    # Wait for not busy.
    in al, 0x64
    test al, 0x2
    jnz seta20.2

    # 0xdf -> port 0x60
    mov al, 0xdf
    out 0x60, al

    # Switch from real to protected mode. Use a bootstrap GDT that makes
    # virtual addresses map directly to physical addressses so that the
    # effective memory map doesn't change during the transition.
    lgdt gdtdesc

    # Protection Enable in cr0 register.
    mov eax, cr0
    or eax, 0x1
    mov cr0, eax

    # Complete the transtion to 32-bit protected mode by using a long jmp
    # to reload cs and eip. The segment descriptors are set up with no
    # translation, so that the mapping is still the identity mapping.

    # This instruction giving me problems.
    ljmp start32, 0x8

.code32
start32:
    # Set up the protected-mode data segment registers
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov ss, ax

    # Zero the segments not ready for use.
    xor ax, ax
    mov fs, ax
    mov gs, ax

    # Set up the stack pointer and call into C.
    mov esp, start
    call bootmain

    # If bootmain returns spin.. ??
spin:
    hlt
    jmp spin

# Bootstrap GDT set up null segment, code segment, and data segment respectively.
# Force 4 byte alignment.
.p2align 2
gdt:
    .word 0x0000, 0x0000
    .byte 0, 0, 0, 0
    .word 0xffff, 0x0000
    .byte 0, 0x9a, 0xcf, 0
    .word 0xffff, 0x0000
    .byte 0, 0x92, 0xcf, 0

# sizeof(gdt) - 1 and address of gdt respectively.
gdtdesc:
    .word (gdtdesc - gdt - 1)
    .long gdt
like image 571
cbot Avatar asked Jun 27 '26 12:06

cbot


1 Answers

In the complete translated code you presented, this line is incorrect:

ljmp start32, 0x8

The proper syntax for a FAR JMP in GNU Assembler's Intel syntax is:

ljmp 0x08, start32

The selector value would be first and the offset second. It seems in translating from AT&T syntax you reversed these 2 values when the order should have remained the same. With the values reversed you would have got the error Error: can't handle non absolute segment in 'ljmp'. In GNU Assembler's Intel syntax you can also substitute ljmp with jmp so jmp 0x08, start32 would work as well.

There are different flavors of Intel syntax. jmp 0x8:start32 is NASM's Intel syntax and it differs from GNU Assembler's Intel syntax where the : and , differ. If you used a : to separate the two values you would get the error Error: junk ':start32' after expression in GNU Assembler.


Notes

  • If the code in bootmain doesn't work it is likely an issue unrelated to the bootloader code you presented in this question. If you are also building all the C code with Intel Syntax rather than AT&T syntax, then make sure all the inline assembly has been properly converted as source and operand would have been reversed as well. xv6 likely has inline assembly in a number of files including xv6-public/x86.h, xv6-public/spinlock.c, xv6-public/usertests.c and xv6-public/stressfs.c
like image 182
Michael Petch Avatar answered Jun 30 '26 08:06

Michael Petch