来自 AT&T 语法的 Intel Assembly ljmp 语法 [英] Intel Assembly ljmp syntax from AT&T syntax
问题描述
我正在尝试将 xv6 引导代码从 At&t 语法转换为 Intel 语法,但我遇到了 ljmp 指令的问题.我正在尝试学习 Intel 计算机的启动过程,并且我对 Intel 汇编不是特别擅长.
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.
最初的 AT&T 语法是 ljmp $0x8, $start32
.
The original AT&T syntax is ljmp $0x8, $start32
.
最小示例:
.code16
jmp 0x8:start32 # won't assemble
.code32
start32:
nop
使用 as -32 -msyntax=intel -mnaked-reg foo.s
和 GNU Binutils 2.35.1 产生错误:表达式后的垃圾 ':start32'
对于远 jmp 行.
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.
我使用 GNU as 和 gcc 工具.
程序集也可能存在其他问题,例如 gdtdesc 和 gdt.
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
推荐答案
在您提供的完整翻译代码中,这一行不正确:
In the complete translated code you presented, this line is incorrect:
ljmp start32, 0x8
在 GNU Assembler 的 Intel 语法中 FAR JMP 的正确语法是:
The proper syntax for a FAR JMP in GNU Assembler's Intel syntax is:
ljmp 0x08, start32
选择器值将是第一个,偏移量第二个.似乎在从 AT&T 语法翻译时,当顺序应该保持不变时,您颠倒了这 2 个值.将值反转后,您将收到错误 Error: can't handle non absolute segment in 'ljmp'
.在 GNU Assembler 的 Intel 语法中,您还可以将 ljmp
替换为 jmp
,这样 jmp 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.
英特尔语法有多种风格.jmp 0x8:start32
是 NASM 的 Intel 语法,它不同于 GNU Assembler 的 Intel 语法,其中 :
和 ,
不同.如果您使用 :
分隔这两个值,您将在 GNU 汇编程序中得到错误 Error:junk ':start32' after expression
.
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.
- 如果
bootmain
中的代码不起作用,则可能是与您在此问题中提供的引导加载程序代码无关的问题.如果您还使用英特尔语法而不是 AT&T 语法构建所有 C 代码,请确保所有内联程序集都已正确转换为源代码和操作数也将被反转.xv6 可能在许多文件中包含内联汇编,包括xv6-public/x86.h
、xv6-public/spinlock.c
、xv6-public/usertests.c
和xv6-public/stressfs.c
- 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 includingxv6-public/x86.h
,xv6-public/spinlock.c
,xv6-public/usertests.c
andxv6-public/stressfs.c
这篇关于来自 AT&T 语法的 Intel Assembly ljmp 语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!