【问题标题】:unable to get assembly program to correctly check a number无法让汇编程序正确检查数字
【发布时间】:2013-09-17 16:30:17
【问题描述】:

我正在尝试编写一个汇编语言程序,它读取一个数字并将其与 5 进行比较。如果数字小于 5,则程序应成功结束,否则应显示错误消息并提示再次输入数字.无论我做什么,我似乎都无法成功结束,它总是跳转到错误标签。

我的代码:

bits 16
org 0x100   ;start at offset 100
jmp main

buffer:   db 4  ; define 4 bytes
      db 0  ; actual number of characters entered

msg:      db "Enter a number between 0 and 5 ", 0ah, 0dh, '$' ; define bytes for message

ermsg:    db "The number must be between 0 and 5", 0ah, 0dh, '$';error message if number is too large

main:
dsp_msg:  mov ah, 09    ; screen display
      mov dx, msg   ; mov starting address of msg into dx 
      int 21h   ; display message

in_buff:      resb 20   ; reserve 20 bytes
      mov ah, 0ah   ; service read character
      mov dx, buffer ;move address of parameter block to dx
      int 21h   ;bios system call
      sub dx, 30h

chk_num:  
      cmp dx, '5'   ;compare entered nnumber to 5
      jge err   ;if entered value is greater or equal to 5 jump to err
      jb fin    ;if entered number is below 5 jump to fin

err:      mov ah, 09    ;
      mov dx, ermsg ;move ermsg to dx
      int 21h   ;display error message
      jmp in_buff     

fin:      int 20h

任何想法我做错了什么?

“更新:

我将代码更改为使用 01 函数
但现在我不断收到错误消息“未指定操作大小”

我的新代码:

bits 16
org 0x100   ;start at offset 100
jmp main

buffer:   db 4  ; define 4 bytes
db 0    ; actual number of characters entered

msg: db "请输入 0 到 5 之间的数字", 0ah, 0dh, '$' ;为消息定义字节

ermsg:    db "The number must be between 0 and 5", 0ah, 0dh, '$';error message if number is too large

main:
dsp_msg:  mov ah, 09    ; screen display
mov dx, msg ; mov starting address of msg into dx 
int 21h ; display message

in_buff:  resb 20   ; reserve 20 bytes
mov ah, 01  ; service read character
mov dx, buffer;move address of parameter block to dx
int 21h ;dos system call

chk_num:  
cmp [dx], 5 ;compare entered nnumber to 5
jge err ;if entered value is greater or equal to 5 jump to err
jb fin  ;if entered number is below 5 jump to fin

err:      mov ah, 09    ;
mov dx, ermsg   ;move ermsg to dx
int 21h ;display error message
jmp in_buff   

fin:      int 20h  

我正在使用 nasm 进行编译。有谁知道这是什么意思?
对不起所有的基本问题。这是我第一次处理汇编语言并发现它非常困难......

【问题讨论】:

  • 单步执行您的代码。注意指令指针的去向以及使用代码0ah 调用int 21h 后会发生什么。另外,请更仔细地阅读代码0ah 的文档。
  • 您能否通过使用代码格式化、将每条汇编指令放在自己的行中并清楚地分隔 cmets 来使您的代码更具可读性?

标签: assembly


【解决方案1】:

您的代码包含:

sub dx, 30h

这会从字符的 ASCII 代码中减去 48 (ASCII 0)。

但您的代码也包含这一行:

cmp dx, '5'   ;compare entered nnumber to 5

将字符的 ASCII 值与减去的值进行比较。

您使用的函数 (0x0A) 正在捕获缓冲输入,因此数据不会放在 DX 上,而是放在 ES:DX 上。只需删除 sub dx, 30h 并且不比较寄存器值,而是那里的数据:

mov ah, 0ah   ; service read character
mov dx, buffer ;move address of parameter block to dx
int 21h       ;bios system call

chk_num:  
    cmp byte [es:dx+2], '5'   ;compare entered number to 5

顺便说一句,您将重写消息数据,因此您的缓冲区应如下所示:

buffer:   
    db 4  ;this buffer will be 4 bytes long
    db 0  ;well, we don't know how many characters are going to be entered, so `0` will be the best
    dd 0  ;and now the promised 4 bytes for buffer contents

您可能对具体的函数参考感兴趣,可以找到here

【讨论】:

    【解决方案2】:
      cmp dx, '5'   ;compare entered nnumber to 5
    

    现在,由于引用了 5,这可能只是与 ASCII 字符 5 (35H) 比较,而不是与值 5 比较。

    我很想删除那些引号。

    【讨论】:

    • 感谢彼得非常详细的回答。使用 01 而不是 0ah 函数会更好吗?
    • 很有可能。这样,您就不需要缓冲区,并且可以逐个字符处理而不是等待 CR。
    【解决方案3】:

    在代码中间声明输入缓冲区可能不是一个好主意。把它放在你跳过的区域,或者section .bss

    int 21h/0Ah 的缓冲区需要进行特殊格式化。第一个字节是接受的最大字符数。使其至少为 2,并且不超过缓冲区中实际留出的空间。第二个字节将包含实际输入的字符数。计数将包括结束输入的 CR...并且它将在缓冲区中。

    实际输入的文本将从[buffer + 2] 开始。不幸的是,[dx + 2] 不是 16 位代码中的有效地址。使用bxsidi 进行寻址。 5'5' 的区别已经讲过了。

    如果您只需要一个字符,您可能不需要“缓冲输入”中断。 Ralf Brown 的中断列表是你的朋友!

    【讨论】:

      猜你喜欢
      • 2016-09-19
      • 1970-01-01
      • 1970-01-01
      • 2017-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      相关资源
      最近更新 更多