【问题标题】:Assembly 8086 program组装8086程序
【发布时间】:2011-03-20 08:37:41
【问题描述】:

我是汇编语言的新手,这是一些我不明白的代码,希望有人能帮忙。

DATA SEGMENT
     VALUES DB 1,2,3,4,5,6,7,8,9
     ITEM DB 6
DATA ENDS
CODE SEGMENT
     ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
       MOV DX,AX
       LEA SI,VALUES
       MOV AL,ITEM
COMPARE: CMP AL,[SI]
         JZ Found
         INC SI
         LOOP COMPARE
         CLC
         JMP EXIT
Found: STC
EXIT: MOV AH,4CH
      INT 21H
      ENDS
CODE END

这个程序应该在1,2,3,4,5,6,7,8,9中寻找号码(6)

我了解它的一般工作原理,但我有几个问题:

  1. 为什么我们使用CLCSTC ??我知道他们将CF 设为零和一,但我们为什么要使用它??
  2. 为什么我们在EXIT 标签之后使用MOV AH,4CH??
  3. 在开始标签之后为什么我们以下内容:

    MOV AX,数据
    MOV DX,AX

我们为什么不直接MOV DX,DATA

最后,有人能推荐一本学习汇编的好书吗?

【问题讨论】:

  • 天哪! 3个编辑器一次! =P 我保留了书籍推荐位。
  • 搜索书籍推荐请参阅:SO Ninja Search
  • LOOP 是 286+,无论如何你都不会在任何地方初始化 cx。
  • @bestsss: loop 绝对不是 286+。 loop的所有形式都是8086级指令。然而,cx 缺乏初始化是真的。

标签: assembly x86-16


【解决方案1】:
MOV AX,DATA

MOV DX,AX

这是错误的。

正确答案是:

MOV AX,DATA   

MOV DS,AX

我们不能直接将数据从内存发送到段寄存器(DS)。所以我们通过通用寄存器(AX)发送。

【讨论】:

    【解决方案2】:

    算法在数字列表中搜索一个数字。

    如果找到,则设置CF。如果没有找到CF则清除。

    INT 21H 是 MS-DOS 服务中断。函数 4Ch 以 AL 中的错误代码结束程序(其中包含要找到的数字)。

    DATA SEGMENT
         VALUES DB 1,2,3,4,5,6,7,8,9
         ITEM DB 6
    DATA ENDS
    CODE SEGMENT
         ASSUME CS:CODE,DS:DATA
    START: MOV AX,DATA
           MOV DX,AX
           LEA SI,VALUES           ; DS:SI points to the VALUES structure
           MOV AL,ITEM
    COMPARE: CMP AL,[SI]           ; Compare with number in list
             JZ Found              ; Jump to Found if equal
             INC SI                ; Try next
             LOOP COMPARE          ;
             CLC                   ; Clear CF (not found)
             JMP EXIT              ; Quit
    Found: STC                     ; Set CF (found)
    EXIT: MOV AH,4CH               ; End program with error code AL = 6.
          INT 21H
          ENDS
    CODE END
    

    【讨论】:

    • 我在问题下提到但 LOOP 是 286,可能你想要 CMP SI、XXX(可能是 ITEM 的地址)和 jnz,而不是循环。在这种情况下,SCASB 可能是最好的。
    【解决方案3】:

    LOOP 指令在这里很奇怪。该指令递减CX 并且仅当CX 不为零时才跳转。这意味着循环运行CX 次,但CX 从未由程序设置。

    CX 在输入时可能为零,第一次递减将使其变为 65535,因此它实际上最多循环 65536 次,如果未找到该元素,则搜索列表末尾。

    为使其正确,请在循环开始前添加MOV CX, ITEM - VALUES。由于ITEM 紧跟在VALUES 之后,减去它们的地址将得到列表中的字节数(元素)。

    通常会在列表末尾添加标签以使此类计算更加稳健。

             VALUES     DB 1,2,3,4,5,6,7,8,9
             VALUES_END LABEL BYTE
             ; ...
    
             MOV CX, VALUES_END - VALUES
    COMPARE: ; ...
             LOOP COMPARE
    

    【讨论】:

      【解决方案4】:
      MOV AX,DATA
      MOV DX,AX
      

      错了。必须是:

      MOV AX,DATA
      MOV DS,AX
      

      我们将数据段的地址写入DS寄存器,这样cpu就知道去哪个地址寻找我们的数据了。由于 x86 指令集的限制,我们不能写MOV DS,DATA,即在 CPU 中没有实现这样的功能。将段地址写入段寄存器时,您必须使用AX 作为媒介。

      【讨论】:

        【解决方案5】:
        • CLC 指令用于“清除进位标志”,STC 用于“设置进位标志”。这些是过程控制指令,用于通过设置/重置标志值来控制处理器动作。
        • 在 ALP 中,我们只能将数据加载到段寄存器中,首先将其加载到通用寄存器中,然后我们必须将其从该通用寄存器移动到段寄存器中,这就是语法.. .
        • MOV AH,4CH 用于终止当前进程。通过将4CH 的十六进制值存储(moving=MOV) 到AH 寄存器中。
        MOV AX,DATA 
        MOV DS,AX 
        
        • MOV AX,DATA指令是加载ax中数据段起始地址的方式。然后通过使用MOV DS,AX,数据段被初始化。

        【讨论】:

        • mov DS, immediate 不能编码为 x86 机器指令,但源必须是 GP 寄存器并不完全正确。也可以将mov es, [bx] 从内存中放入段寄存器(felixcloutier.com/x86/mov),甚至将pop ds 放入其中。这对于data 段没有用here,但您的声明并没有将其限制在该用例中。
        • 另外,mov ah, 4Ch 本身不会终止程序。 int 21h 处理程序在 AH 中查找索书号;这就是在运行 int 21h 之前将其设置为 DOS 调用号的原因。
        猜你喜欢
        • 1970-01-01
        • 2023-03-17
        • 1970-01-01
        • 2015-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多