【问题标题】:Assembly Language - What is the register of an temp string input汇编语言 - 什么是临时字符串输入的寄存器
【发布时间】:2016-03-03 07:54:58
【问题描述】:

我一直在比较固定字符串和输入字符串。但很难弄清楚输入的寄存器是什么,是alah 还是其他什么。我只是一个初学者,这对于程序员 lol jk 来说是一种痛苦的语言。请帮助我真的很感激谢谢:)

mov dx, offset temp             ;string input
mov ah, 0ah
int 21h     

mov bl, "a"                     ;condition
cmp al, bl 
jne aw

mov dx, offset msgTrue          ;true
mov ah, 09
int 21h  

aw:                             ;false
mov dx, offset msgFalse
mov ah, 09
int 21h 


ret
    msg  db 10, 13, "           *         ************************************       *****$"
    msg1 db 10, 13, "          ***        *            Ticketing System      *        ***$"
    msg2 db 10, 13, "         *****       ************************************         *$" 
    msg3 db 10, 13, "                          ==========================$" 
    msg4 db 10, 13, "                          =  (a)Land               =$" 
    msg5 db 10, 13, "                          =  (b)Water              =$"
    msg6 db 10, 13, "                          =  (c)Air                =$" 
    msg7 db 10, 13, "                          ==========================$" 
    msg8 db 10, 13, "                           Choose Travel Type: $"
    temp db 2, 0, 3 dup("$") 

    msgTrue db 10, 13, "                           You selected Land$"
    msgFalse db 10, 13, "                           Invalid Input$" 

【问题讨论】:

  • 请注意,您不需要标记msg1 / msg2 等。您可以只使用未标记的db 行。

标签: assembly emulation emu8086


【解决方案1】:

您使用系统调用 0Ah(缓冲输入)http://spike.scu.edu.au/~barry/interrupts.html#ah0a,因此您读取的数据位于 temp(缓冲区)中

0Ah 从 STDIN 读取 n 个字节到缓冲区中

mov bx, OFFSET buffer将缓冲区的地址(这里是temp)推入bx,0Ah需要这个

要修复读取的字节数,您可以使用例如mov byte [bx],15

另见http://www.fysnet.net/kbbuffio.htm

mov bl, 'a'                     ;condition
cmp al, bl 
jne aw

比较两个 8 位值(字符),请参见 http://x86.renejeschke.de/html/file_module_x86_id_35.html(AL、AH 是 8 位,AX 是 16 位,EAX 是 32 位(扩展 AX))

请参阅https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture#General-purpose_registers_(16-bit_naming_conventions) 了解 8-/16-/32-/64 位命名约定

这可用于从输入缓冲区temp中读取读取的输入字节并进行比较:

val DB 'a'
mov al, val                    ;condition
mov bx, OFFSET temp            ; address of temp in bx: bx is a pointer to first byte in temp now
;alternatively you can use  lea bx, [temp] 
add bx, 2                     ; structure of input buffer (here temp) http://spike.scu.edu.au/~barry/interrupts.html#dosbuf
mov dl, byte [bx]              ; writes the byte [bx] points to in dl - [bx] dereferences bx - the byte command treats bx as a char* - see https://www.cs.uaf.edu/2006/fall/cs301/lecture/10_02_pointer.html
cmp al, dl 
jne aw

【讨论】:

  • 为什么不指出cmp al, 'a' 会更简单呢?当立即数可以相同时,无需绑定 bl。 cmp-immediate-with-al 甚至还有一个特殊的编码,所以即使是立即数,它也只有一个 2 字节的指令。另外,您认为mov bl, 'a' 有什么问题?大多数汇编程序允许您在任何可以出现整数常量的地方使用字符常量。多字符常量产生多字节整数。
  • cmp byte [temp], 'a' / jne 相比仍然很笨拙。还要注意16bit的有效地址不能用dx作为base或者index,只能BX/BP+SI/DI。 16bit can't use a SIB byte, so they have to jam all the addressing modes into the mod/rm byte。这只是 16 位代码糟糕且浪费时间学习的众多原因之一。 (这些限制在其他模式中不存在)。
  • 我不打算这样做,但我不能单独留下低效的代码。 >.offset temp + '3' 与offset temp + 3 不同。您正在添加 ascii 编码 >.+2吗?第一个用户输入字符在两个 count 字节之后,对吧?
  • 你说得对,它是+2。第一次读取时,它认为缓冲区中的字节 02 也具有“管理功能”(然后开始用户字节......)
  • 您的代码还有其他问题:[dx] 不是有效的有效地址。您的代码不会汇编。使用bxbpsidi。例如mov si, offset temp + 2/cmp byte ptr [si], 'a'。 (16bit does allow displacement-only effective addresses。32 位有效地址是相同的,但没有限制,您可以缩放索引。(请参阅我之前评论中的链接,了解我在 32 位 EA 上所做的文章)。但是,如果您愿意,您可以浪费说明将内容放入 regs 中:P
【解决方案2】:

结果在内存中,您要求系统调用将其放入其中。请参阅 Ralf 的回答。

像这样检查输入:

    mov   dx, offset temp             ; input buffer
    mov   ah, 0ah                     ; buffered input syscall
    int   21h     

    ; select one of two messages to print
    mov   dx, offset msgTrue
    cmp   byte ptr [temp+2], 'a'      ; compare the first byte of user input
    je  .true
    mov   dx, offset msgFalse         ; conditionally skip this instruction
.true:

    mov ah, 09                        ; print string syscall
    int 21h

注意mov ah / int 0x21 代码只出现一次,并且分支只跳过一条指令。您可以在现代 CPU 上使用 cmov 来实现,但令人讨厌的是 cmov 没有立即源编码。

请参阅 Ralf 的答案中的 cmets,以批评由于不只是将直接操作数与 cmp 一起使用而导致的臃肿代码。在使用汇编时常量时,这样占用的寄存器也会少很多。


另一个选项(而不是mov dx, offset msgFalse)是add dx, offset msgFalse - msgTrue,它使立即数操作数很小(适合使用imm8 编码的-128 .. 127 范围)。但是,它不会在 16 位代码中保存任何代码字节,因为 mov dx, imm16 是 3 个字节(每个 dest 寄存器的专用操作码),而 add dx, imm8 也是三个字节(没有专用操作码)。这将节省 32 位代码中的字节,其中地址为 32 位。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-27
    相关资源
    最近更新 更多