【问题标题】:Why isn't my code working when adding .386?为什么我的代码在添加 .386 时不起作用?
【发布时间】:2020-10-17 12:52:22
【问题描述】:

如标题中所述,我需要使此代码能够执行与仅使用 16 位相同的操作,但将 .386 添加到代码中,以便我可以使用 32 位寄存器。但是当我现在添加 .386 时,我的代码没有打印任何东西,知道如​​何解决这个问题。我的 mov 作为 @data 有问题还是我需要添加其他内容?我正在使用 TASM

TITLE Programa de prueba(prueba.asm)
.386                              
.model small
.stack 

.data

escoga db 10,13,7, 'Escoga la operacion: 1. x and y, 2. x or y, 3. not x, 4. x xor y, 5. terminar:  
', '$'

digite1 db 10,13,7, 'Digite el primer numero hexadecimal: ', '$'
digite2 db 10,13,7, 'Digite el segundo numero hexadecimal: ', '$'
Yval db "Enter Y hexadecimal value: ",0
resultStr db "The result is: ",0
result db ?
x db 8 DUP(' '),'$'
y db 8 DUP(' '),'$'
num db 1 DUP(0),'$'

.code
main proc
    mov ax, @data
    mov ds, ax

.loop1:
    cmp si, 82 
    je .done1 
    mov ah, 0Eh 
    mov al, escoga[SI] 
    mov bh, 00h 
    int 10h 
    inc si 
    jmp .loop1

.done1:
    mov si, 0
    mov di, 0
.inp1:
    cmp si, 1 
    je .ext1 
    mov ah, 00h 
    int 16h 
    inc si 
    inc di 
    jmp .modi1 

.modi1:
    mov num[di], al 
    mov ah, 0Eh 
    mov al, num[di] 
    mov bh, 00h 
    int 10h 
    jmp .inp1 

.ext1:
    mov si, 0
.ext2:
    cmp si, 2
    je .salir
    mov ah, 0Eh 
    mov al, num[SI] 
    inc si 
    jmp .ext2

.salir:
    cmp num[SI-1], '5'
    jge .term
    jmp .term2
    
.term2:
    mov si, 0
 
.loop2:
    cmp si, 40
    je .done2
    mov ah, 0Eh 
    mov al, digite1[SI] 
    mov bh, 00h 
    int 10h 
    inc si 
    jmp .loop2

.done2:
    mov si, 0
    mov di, 0

.inp2:
    cmp si, 8 
    je .ext3 
    mov ah, 00h 
    int 16h 
    inc si 
    inc di 
    jmp .modi2 

.modi2:
    mov x[di], al 
    mov ah, 0Eh 
    mov al, x[di] 
    mov bh, 00h 
    int 10h 
    jmp .inp2

.ext3:
    mov si, 0 
    mov di, 0

.loop3:
    cmp si, 41
    je .done3
    mov ah, 0Eh 
    mov al, digite2[SI] 
    mov bh, 00h 
    int 10h 
    inc si 
    jmp .loop3

.done3:
    mov si, 0
    mov di, 0

.inp3:
    cmp si, 8 
    je .ext4 
    mov ah, 00h 
    int 16h 
    inc si 
    inc di 
    jmp .modi3 

.modi3:
    mov y[di], al 
    mov ah, 0Eh 
    mov al, y[di] 
    mov bh, 00h 
    int 10h 
    jmp .inp3

.ext4:
    mov si, 0 
    mov di, 0    

.term:
.exit
 
main endp  

end main

【问题讨论】:

  • 为什么你的.loop1循环使用si,而此时你还没有初始化si
  • 你就在那里,但它仍然使用 si 就好像它有 0
  • 如果将.386 放在.model small 之后而不是之前会发生什么,所以将其更改为.model small .386
  • 是的,您将能够在 16 位代码中使用 32 位寄存器。

标签: assembly x86 32-bit tasm real-mode


【解决方案1】:

MASM 6.1 documentation 是编写实模式分段代码(非 FLAT 模型)的好资源。即使您使用的是 TASM,MASM 文档仍然是一个很好的参考。您遇到的是一种相当微妙的代码生成方式的副作用,该方式取决于您将.386 指令相对于.MODEL 指令放置的位置。 设置段字大小(仅限 80386/486) 部分记录了这种微妙的行为:

设置分段字长(仅限 80386/486)

SEGMENT 指令中的使用类型指定了段字的大小 在 80386/486 处理器上。分段字长决定默认值 段中所有项目的操作数和地址大小。尺寸属性 可以是 USE16、USE32 或 FLAT。 如果您指定 .386 或 .486 .MODEL 指令之前的指令,USE32 是默认值。这 属性指定段中的项目使用 32 位偏移而不是 16 位偏移。如果 .MODEL 在 .386 之前 或 .486 指令,USE16 是默认值。 要使 USE32 成为默认值, 将 .386 或 .486 放在 .MODEL 之前。您可以覆盖 USE32 默认值 使用 USE16 属性,反之亦然。

您需要注意的是您放置.386 的位置。您已将它放在.model 之前,因此汇编程序默认所有部分都是USE32。这意味着正在生成的所有指令都是在假设处理器以 32 位模式运行的情况下进行编码的。 32 位编码指令在 16 位代码中无法正常运行,是您的程序失败的原因。

您正在编写将在 16 位实模式下运行的代码(可能使用 386 条指令和寄存器),因此我相信您在使用 .code.data 指令时会希望确保 USE16 是默认值.要获得您想要的行为,您必须进行此更改:

.386
.model small

收件人:

.model small
.386

【讨论】:

  • 哇——你一定喜欢 x86。以及它所有的汇编程序!
  • @ErikEidt:完全有可能不喜欢任何类似 MASM 的 16 位 DOS 汇编器及其用于指定默认操作数大小(CPU 模式)的奇怪指令怪癖与是否允许 CPU features 如通过前缀推送立即 (186) 或 32 位操作数大小。 :P
猜你喜欢
  • 2014-01-23
  • 2013-08-06
  • 1970-01-01
  • 2016-01-23
  • 2011-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多