Assembly 这个实模式代码有什么问题
我有一段在realmode下运行的代码,并在屏幕上打印一条消息,我使用Dosbox 0.7作为我的执行环境Assembly 这个实模式代码有什么问题,assembly,x86,real-mode,Assembly,X86,Real Mode,我有一段在realmode下运行的代码,并在屏幕上打印一条消息,我使用Dosbox 0.7作为我的执行环境 jmp 0x7c0:start start: mov ax, cs ; set up segments mov ds, ax mov es, ax mov al,03h mov ah,0 int 10h welcome db "This is insane now" mov si, welcome call print_string print_string:
jmp 0x7c0:start
start:
mov ax, cs ; set up segments
mov ds, ax
mov es, ax
mov al,03h
mov ah,0
int 10h
welcome db "This is insane now"
mov si, welcome
call print_string
print_string:
lodsb ; grab a byte from SI
or al, al ; logical or AL by itself
jz .done ; if the result is zero, get out
mov ah, 0x0E
int 0x10 ; otherwise, print out the character!
jmp print_string
.done:
ret
我可以很好地汇编这段代码,但当我运行这段代码时,它就挂在那里,我可以在linux终端中看到一条消息
Illegal read from b0671921, CS:IP 7c0: 4468
我就是这样组装的
nasm PRINT.ASM -o out.com
我试着在谷歌上搜索这条消息,发现DOSBox版本可能有问题
有人能告诉我这里有什么问题吗?让我们一步一步:
jmp 0x7c0:start ;jump to start
start:
mov ax, cs ; set up segments
mov ds, ax
mov es, ax
mov al,03h ; Set up screen to 80 by 25
mov ah,0
int 10h
字符串不是可执行代码,所以请将其放在start
label之前和jmp之后。
字符串必须以零字符结尾
welcome db "This is insane now"#0
mov si, welcome ;Print string
call print_string
缺少正确退出程序的最终确定代码,因此将再次执行print\u string
print_string:
cld ;Clear direction flag instruction is missing
lodsb
or al, al ; test if zero char
jz .done ; exit if zero char
mov ah, 0x0E ; Write Char in Teletype Mode
mov bh, 0 ; Define 0 page if we have multiple pages
int 0x10 ; print character!
jmp print_string
.done:
ret
代码的问题是字符串常量的位置。它必须放在永远不会被“执行”的地方,因为它不是代码 另一个问题是代码如何结束。引导记录应该加载一些其他代码(OS内核或更大的引导程序)并跳转到它。或者至少(如果您只想测试某些东西)简单地进行无限循环。在您的情况下,程序会转到print_string子例程,然后尝试“返回”到任何地方 以下是固定版本:
org 7c00h
start:
mov ax, cs ; set up segments
mov ds, ax
mov es, ax
mov al, 03h
mov ah, 0
int 10h
mov si, welcome
call print_string
.sleep:
jmp .sleep
print_string:
lodsb ; grab a byte from SI
test al, al ; logical or AL by itself
jz .done ; if the result is zero, get out
mov ah, 0x0E
int 0x10 ; otherwise, print out the character!
jmp print_string
.done:
ret
welcome db "This is insane now", 0
为什么跳转被移除?BIOS从磁盘加载引导扇区后,将其置于地址0000h:7c00h。分别跳到$0000:$7c00以开始执行代码
只要(可能)初始代码在偏移量$0000处编译,第一次跳转只需将段更改为7c0h,并将偏移量更改为0000h,以提供程序的正确执行
但是我们可以将程序的源代码设置为7c00h(org 7c00h),这样就可以避免再使用一条指令。您是否正在尝试编写引导加载程序?COM文件在地址0x100处加载,因此不能以这种方式运行引导加载程序。您必须创建一个虚拟软盘驱动器或硬盘驱动器,将引导加载程序二进制文件放在第一个扇区中。另外,您的欢迎字符串缺少一个NUL终止符,不应该放在代码中间,因为CPU不知道代码和数据之间的区别。如果您真的想要创建一个.com文件(而不是引导加载程序),则应该使用<代码> [org 0x100] < /COD>并在开始时删除<代码> JMP < /代码>。(并修复字符串变量的上述问题)。感谢Micheal,我将尝试一下。感谢GJ.的响应。我只是想知道我是否以正确的方式组装了此代码??感谢@johnfound提供的答案,我想问您几个疑问1)为什么jmp 0x7c0:start已从代码中删除,尽管Micheal在上面解释了这件事,但他也想听听你的意见。或者至少(如果你只想测试某个东西)简单地做一个无限循环,你能更详细地解释它吗?或者如果在你的答案中添加它的细节会更好。@amitsightomar现在答案已经确定了。未测试,但应该可以。再次感谢Johnfound,它将测试它并让您知道结果。字符串应该有一个NUL终止符,因为
print\u string
函数依赖于此。@amitsightomar您是如何测试此程序的?它必须写入某些媒体的MBR中,然后从中引导。如果您想在DOS中测试它,只需将7c00h替换为100h,将无限循环替换为“ret”。但在这种形式下,它不能用作引导扇区。