assembly - 来自 AT&T 语法的 Intel Assembly ljmp 语法

标签 assembly x86-16 gnu-assembler att intel-syntax

我正在尝试将 xv6 引导代码从 At&t 语法转换为 Intel 语法,但我遇到了 ljmp 指令问题。我正在尝试学习 Intel 计算机的启动过程,但我对 Intel 汇编并不是特别擅长。

原始的 AT&T 语法是 ljmp $0x8, $start32

最小的例子:

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

.code32
start32:
   nop

在 GNU Binutils 2.35.1 中使用 as -32 -msyntax=intel -mnaked-reg foo.s 生成
错误:junk ':start32' after expression for the far jmp line.

我正在使用 GNU as 和 gcc 工具。
程序集也可能存在其他问题,例如 gdtdesc 和 gdt。

移植到 Intel 语法的完整代码是:

# 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

最佳答案

在您提供的完整翻译代码中,这一行是不正确的:

ljmp start32, 0x8

GNU 汇编程序的英特尔语法中 FAR JMP 的正确语法是:

ljmp 0x08, start32

首先是选择器值,其次是偏移量。似乎在从 AT&T 语法翻译时,您颠倒了这 2 个值,而顺序应该保持不变。如果值反转,您将得到错误 Error: can't handle non absolute segment in 'ljmp'。在 GNU 汇编程序的 Intel 语法中,您还可以将 ljmp 替换为 jmp,这样 jmp 0x08, start32 也可以工作。

有不同风格的英特尔语法。 jmp 0x8:start32 是 NASM 的 Intel 语法,它不同于 GNU Assembler 的 Intel 语法,其中 :, 不同。如果您使用 : 来分隔这两个值,您将在 GNU 汇编程序中收到错误 Error: junk ':start32' after expression


注意事项

  • 如果 bootmain 中的代码不起作用,则可能是与您在本问题中提供的引导加载程序代码无关的问题。如果您还使用 Intel 语法而不是 AT&T 语法构建所有 C 代码,请确保所有内联汇编都已正确转换,因为源和操作数也会被反转。 xv6 可能在许多文件中都有内联汇编,包括 xv6-public/x86.hxv6-public/spinlock.cxv6-public/usertests。 cxv6-public/stressfs.c

关于assembly - 来自 AT&T 语法的 Intel Assembly ljmp 语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65347376/

相关文章:

assembly - ModRM : Can't use direct address, 组件 x86

ios - 如何跟踪内存中地址的值?

programming-languages - 值得学习汇编语言吗?

assembly - 赋值指令未将新值分配给 emu8086 中的符号

assembly - 在汇编中打印 3 位数字

assembly - 告诉 GAS 在 Intel 语法模式下使用分号进行注释

java - 如何为 java 扫描器使用多个分隔符

assembly - 8086汇编键盘ISR实现

arrays - .text .data 和 main 的段错误(.data 部分中的 main)

assembly - 如何使用 GNU GAS 汇编器生成像 nasm -f bin 这样的普通二进制文件?