Assembly 在汇编x86实模式下寻址是如何工作的?为什么标签返回不同的值?
我有两种版本的引导加载程序代码(它应该在512b引导加载程序代码之后移动1kb堆栈)。 开始物理地址始终为0x7c00(标签“开始”)。BIOS将引导加载程序代码复制到RAM中。 当我使用“MOV SP,启动+1024+512”时:Assembly 在汇编x86实模式下寻址是如何工作的?为什么标签返回不同的值?,assembly,x86,nasm,bootloader,real-mode,Assembly,X86,Nasm,Bootloader,Real Mode,我有两种版本的引导加载程序代码(它应该在512b引导加载程序代码之后移动1kb堆栈)。 开始物理地址始终为0x7c00(标签“开始”)。BIOS将引导加载程序代码复制到RAM中。 当我使用“MOV SP,启动+1024+512”时: SP将是0x7c00+1024+512,因为物理地址应该是SS:SP=0 。。。始终转到地址0x7c00。它将计算 在分段内存模型中,您不应该只考虑有效(物理)地址,还必须始终将地址视为实模式下的(16+16)位值或16位保护模式下的(16+32)位值或32位保护模
mov al,cs:[100h]
此指令将从地址
CS:0x100
读取一些字节,该地址实际上是(你能把重点放在这一点上吗?这里似乎有至少10个问题,大约有9个太多了,我甚至不知道如何在不写一本关于8086内存体系结构的书的情况下开始回答。但也许是有帮助的。一些生物传感器会将CS:IP设置为0000:7c00
,其他设置为07c0:0000
。实验室会发生什么elstart
独立于此,由您在源代码中为org
选择的值决定。您确实需要将段和偏移分开,因为CPU就是这样做的;它只在最后一个阶段将它们转换为物理地址。jmp main
很可能是一个相对的问题或“短”跳转。汇编程序计算jmp main
指令本身和标签main
之间的字节数,并将差异编码到地址中。执行时,CPU将此值添加到程序计数器IP,而不使用CS。因此,无论段寄存器如何设置,它都能正常工作,并且不受影响呃,代码恰好加载到内存中。谢谢@NateEldredge您回答了我所有的问题=)额外感谢jmp。我忘记了这个机制。更正:它是jmp main
之后的下一条指令与标签main
之间的字节数。对于短跳转和近直接跳转都是如此,问题是这个差分适合8位符号扩展立即数还是16位。
mov SI, main
lodsb ;write data from main to AL
[bits 16]
[org 0x7c00]
start: ;offset= 0x7c00
jmp main
db "Some data" ;actually fake BIOS Parameter Block(BPB)
main:
mov ax, 0
mov ds, ax ; data segment =0.
mov ss, ax ; stack segment = 0
mov sp, start+1024+512 ;stack pointer = 0x7c00+1024+512
[bits 16]
[org 0x0000]
start: ;offset= 0x0000
jmp main
db "Some data" ;actually fake BIOS Parameter Block(BPB)
main:
mov ax, 0x07c0
mov ds, ax ; data segment =0x07c0.
mov ss, ax ; stack segment =0x07c0.
mov sp, start+1024+512 ;stack pointer = 0+1024+512