为什么我的代码在添加 .386 时不起作用?

Die*_*vel 5 x86 assembly 32-bit real-mode tasm

正如标题中所解释的,我需要让这段代码能够做与仅使用 16 位相同的事情,但将 .386 添加到代码中,以便我可以使用 32 位寄存器。但是当我现在添加 .386 时,我的代码没有打印任何内容,不知道如何解决这个问题。我的 mov as 有问题吗,@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
Run Code Online (Sandbox Code Playgroud)

Mic*_*tch 7

MASM 6.1的文档是一个很好的资源用于编写实模式分割的码(非平面模型)。即使您使用的是 TASM,MASM 文档仍然是一个很好的参考。你所遇到的是在根据代码生成一个相当微妙的方式的副作用在那里您将.386指令相对.MODEL指令。这种微妙的行为记录在设置段字大小(仅限 80386/486)部分中

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

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

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

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

.386
.model small
Run Code Online (Sandbox Code Playgroud)

到:

.model small
.386
Run Code Online (Sandbox Code Playgroud)

  • @ErikEidt:完全有可能不喜欢任何类似 MASM 的 16 位 DOS 汇编器及其奇怪的指令怪癖,用于指定默认操作数大小(CPU *模式*)与是否允许 CPU *功能*,如推送立即( 186) 或通过前缀的 32 位操作数大小。:P (2认同)