NASM 编译器 - 产生机器码“66”,导致无法正确打印

【问题描述】

代码hello-DOS.asm,实现功能:打印“hello world”

; hello-DOS.asm - single-segment, 16-bit "hello world" program
;
; assemble with "nasm -f bin -o hi.com hello-DOS.asm"
[BITS 32]

    org  0x100        ; .com files always start 256 bytes into the segment

    ; int 21h is going to want...


    mov  dx, msg      ; the address of or message in dx
    mov  ah, 9        ; ah=9 - "print string" sub-function
    int  0x21         ; call dos services

    mov  ah, 0x4c     ; "terminate program" sub-function
    int  0x21         ; call dos services

    msg  db 'Hello, World!', 0x0d, 0x0a, '$'   ; $-terminated message

通过nasm -f bin -o hi.com hello-DOS.asm

编译后,执行hi.com,却什么也没打印出来。

 如下:

 

 通过debug调试,发现第一个执行的指令竟然是“66”!!!

 

 

【问题分析】

按照正常的逻辑,第一条指令mov dx, msg

应该是BA 0C 01,

查看hi.com的二进制文件,发现了BA 0C 01,但前面还多了个66

 

“66”指令当然无法正确执行,于是尝试修改为一条NOP指令,即先让第一条指令执行一个空指令。

于是直接更改66 为 90(NOP指令对应的二进制为90),如下:

 

 

最后,再执行,得到了正确的结果。 

 

问题的原因找到了,就是因为nasm编译时多产生了一个“66”指令,那么怎么解决呢?

 

【问题解决】

多种尝试,发现更改[BITS 32]为[BITS 16]后,就不会产生“66”指令。

因此大致可以确定是由于16位和32位原因造成的该问题。

仔细分析代码,

发现mov dx,msg 使用的是dx,是不是应该使用32位的edx呢?

尝试将dx更改位edx,问题解决。

最终代码如下:(只更改了一行)

; hello-DOS.asm - single-segment, 16-bit "hello world" program
;
; assemble with "nasm -f bin -o hi.com hello-DOS.asm"
[BITS 32]

    org  0x100        ; .com files always start 256 bytes into the segment

    ; int 21h is going to want...

    mov  edx, msg      ; 重点再这里,32位要用edx the address of or message in dx
    mov  ah, 9        ; ah=9 - "print string" sub-function
    int  0x21         ; call dos services

    mov  ah, 0x4c     ; "terminate program" sub-function
    int  0x21         ; call dos services

    msg  db 'Hello, World!', 0x0d, 0x0a, '$'   ; $-terminated message

 [经验教训]

 对于汇编中的中断打印函数,32位下使用对应的寄存器,可能才会有对应的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灰暗角落里的琴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值