繁体   English   中英

x86汇编程序(nasm)的数据段问题用于打印功能

[英]Data segment issue with x86 Assembler (nasm) for print function

我正在玩x86汇编程序,因为我想刷新我的低级编程技巧:-)。 出于测试目的,我尝试编写一个只打印出给定字符串的函数。 打印功能本身工作正常。 在另一个步骤中,我想从磁盘跳转到它加载第二个汇编程序,然后打印出一个文本。 在跳转到地址时从磁盘加载工作正常。

这是给定的场景:

[... loading from disk etc ... program is loaded to 0x7e0:0001]

jmp 0x7e0:0001

[... context of other asm ...]

jmp Start
;data fields
msg db "Hello World!",0

Start:
     xor si, si     ; clear SI register
     mov si, msg    ; load message to SI register

     call Print

     cli
     hlt            ; halt the system

Print:
     .PrintLoop:
         lodsb                ; load byte from SI register
         or al, al            ; check if 0 byte
         jz short .PrintDone  ; if so - stop
         mov ah, 0Ah          ; function - print text to cursor
         int 0x10             ; BIOS interrupt

         jmp .PrintLoop       ; continue with next char
     .PrintDone:
         ret

所有这个程序都运行正常。 我面临的唯一问题是,没有打印文字。 在调试过程中,我看到print函数立即跳转到.PrintDone标签,因为SI中似乎没有数据,因此lodsb不会加载任何数据(除了null字节)。

我在想这个事实,数据段可能有问题。

因此,我在Start-Routine的开头添加了以下行:

xor ax, ax    ; clear ax register
mov ax, cs    
mov ds, ax    ; set data segment pointer

但这对程序行为没有任何改变。 什么都没打印。

执行到达暂停指令时检查CPU寄存器,给出以下结果:

EAX=00000a00 EBX=00000000 ECX=00000002 EDX=00000000
ESI=00000026 EDI=00000000 EBP=00000000 ESP=0000ffff
EIP=00000036 EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=1
ES =07e0 00007e00 0000ffff 00009300
CS =07e0 00007e00 0000ffff 00009b00
SS =9000 00090000 0000ffff 00009300
DS =07e0 00007e00 0000ffff 00009300

你有什么线索在这里发生了什么吗?

[编辑 - 问题已解决]

更换:

mov ah, 0Ah -> mov ah, 0xE

解决了这个问题!

最好的塞巴斯蒂安

有一些问题。

首先,您没有正确设置功能0Ah的寄存器。 您必须将bh设置为页码(0),将cx设置为重复计数(1)。

其次,这个BIOS功能不会使光标位置前进,所有字符都会被打印到屏幕上的相同位置,相互覆盖,这应该只会导致'!' 可见,因为它是最后一个角色。

我建议改用函数0Eh。

第三,你没有初始化lodsb依赖的方向标志( flags.df )。 您应该使用cld重置df

第四,我没有看到所有代码,但是你应该使用正确的org指令为指令和数据生成正确的偏移量。

此外, NMIsSMIs将导致hlt完成, hlt的代码将执行(以下是您的Print )。 你想在循环中执行hlt

通过这些修复,我们得出:

bits 16
org 1

jmp Start
;data fields
msg db "Hello World!",0

Start:
     mov ax, cs    
     mov ds, ax    ; set data segment pointer
     cld

     mov si, msg    ; load message to SI register

     call Print

     cli
.halt:
     hlt            ; halt the system
     jmp .halt

Print:
     .PrintLoop:
         lodsb                ; load byte from SI register
         or al, al            ; check if 0 byte
         jz short .PrintDone  ; if so - stop
;         mov ah, 0Ah          ; function - print text to cursor
;         xor bh, bh
;         mov cx, 1
         mov ah, 0Eh          ; function - print text tty

         int 0x10             ; BIOS interrupt

         jmp .PrintLoop       ; continue with next char
     .PrintDone:
         ret

通过编译上面的nasm blah.asm -f bin -o blah.bin得到的二进制文件应该加载到0x7e0:0001并跳转到jmp 0x7e0:0001

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM