我一直在尝试使用ASSUME编写汇编代码,但一直遇到无法找到其原因的错误。以下是几个示例: 示例1
.286
.model medium, c
pproc typedef ptr proc
.data
dummy db ?
.code
assume bx:ptr pproc
call [bx]
end
组装后没有错误。
如果将.286更改为.386,则会出现以下错误:
Error A2158: type is wrong size for register
。
该行发生此错误:
Assume bx:ptr proc
为什么会发生?在ASSUME中需要更改哪些内容以纠正错误?
注意:我注意到pproc被汇编程序定义为FAR指针。为什么?
示例2:
.286
.model medium
.data
dummy db ?
.code
assume bx:near ptr
call [bx]
call near ptr [bx[
end
现在,如果我只是将.286更改为.386,则会收到以下汇编错误:
assume bx:near ptr
A2158: Type is wrong size for register
为什么会出现此错误?这是一个近段。请注意,执行相同操作的指令没有假设。
示例3
.286
.model medium, c
.data
dummy db ?
.code
assume bx:ptr byte
mov [bx],12h
mov byte ptr [bx],12h
end
现在,如果我只是将.286更改为.386,当出现以下错误时 尝试组装
对于行:assume bx:ptr byte
,我得到了错误
A2158: Type is wrong size for register
为什么会发生?在ASSUME中需要更改哪些内容以纠正错误?
对于行:mov [bx],12h
发生以下错误:error 2070 :invalid instruction operands.
为什么会出现此错误?这是错误吗?这应该工作,我正在尝试
将12h
存储到[bx]
中。请注意,执行相同操作的指令没有假设。
答案 0 :(得分:3)
MASM 6.1 documentation是编写实模式分段代码(非FLAT模型)的良好资源。第43-47页上有关于ASSUME和段字长的良好信息。您遇到的是一种相当微妙的方式的副作用,即ASSUME将根据相对于.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
。您似乎正在编写将以16位实模式运行的代码(可能使用386指令和寄存器),因此我相信您需要确保在使用USE16
和{时,.code
是默认的{1}}指令。要获得想要的行为,我想您可能希望考虑更改:
.data
收件人:
.386
.model medium, c
观察发生的情况。
这是我认为您遇到的第二个问题。 MASM 5.1中添加了此supplemental information,这可能有助于您了解.model medium, c
.386
和FAR PTR
的问题。内容如下:
PTR运营商
PTR运算符可用于指定用于CALL或JMP指令的寄存器间接操作数的大小。但是, 不能使用NEAR或FAR指定大小。请改用WORD或DWORD。 (在80386 32位段中,使用DWORD或FWORD。)显示了示例 下方:
NEAR PTR
此限制仅适用于寄存器间接操作数。 NEAR或 FAR可以应用于与标签关联的操作数。示例是 如下所示:
; 8086, 80826, or 80386 16-bit mode jmp WORD PTR [bx] ; Legal near jump call NEAR PTR [bx] ; Illegal near call call DWORD PTR [bx] ; Legal far call jmp FAR PTR [bx] ; Illegal far jump ; 80386 32-bit mode only jmp DWORD PTR [bx] ; Legal near jump call NEAR PTR [bx] ; Illegal near call call FWORD PTR [bx] ; Legal far call jmp FAR PTR [bx] ; Illegal far jump
在 jmp NEAR PTR pointer[bx] ; Legal
call FAR PTR location ; Legal
部分中,如果要进行间接FAR JMP / CALL使用,则:
USE32
如果您想在pproc typedef ptr fword
部分中进行近距离间接呼叫,请执行以下操作:
USE32
在pproc typedef ptr dword
部分中,如果要进行间接FAR JMP / CALL使用,则:
USE16
如果您想在pproc typedef ptr dword
部分中进行近距离间接呼叫,请执行以下操作:
USE16
答案 1 :(得分:2)
在所有示例中,您都告诉MASM考虑bx
指向某物 1 的指针(首先是一个过程,而不是任何东西,而不是字节),并且在所有情况下,这些指针都是near(除非另有声明,否则为隐式)。
如果您指定.286
,则MASM将创建一个默认数据段,假定该段可以通过16位寻址,这与默认代码段相似(默认操作数/地址大小为16位)。
如果使用.386
,则会创建32位版本。
指向16位数据段的近指针是16位,指向32位数据段的近指针是32位。
寄存器bx
始终是16位。
因此,.386
和ASSUME BX: PTR <SOMETHING>
不能正常工作。
1
我认为这对于某些丑陋的高级混合很有用,例如警告您是否加载/存储其他类型或允许您访问结构成员。
ASSUME
对于段环境中的段寄存器非常有用/必不可少,official documentation在完全掩盖其上似乎是灾难性的不完整。
答案 2 :(得分:0)
经过大量测试,我发现了以下格式的ASSUME语句的“规则”:ASUME寄存器:PTR大小
“ ASSUME reg:PTR {Size}
的允许设置Cases where cpu instruction is BEFORE .MODEL or no cpu instruction before .MODEL:
|user supplied | condition
| values |
| reg | size |
.286 instruction or less is |8-bit | BYTE |can only use BYTE, no PTR |
before tiny,small or medium |16-bit | WORD |if <WORD or >WORD requires PTR|
.MODEL or no cpu instruction
before tiny,small or medium
.MODEL. Causes internal use16.
|user supplied | condition
| values |
| reg | size |
.286 instruction or less is |8-bit | BYTE |can only use BYTE, no PTR |
before compact,large,or huge |16-bit | WORD |can only use WORD, no PTR |
.MODEL or no cpu instruction
before compact,large or huge
.MODEL. Causes internal use16.
|user supplied | condition
| values |
| reg | size |
.386 instruction or greater is |8-bit | BYTE |can only use BYTE, no PTR |
before tiny,small or medium |16-bit | WORD |can only use WORD, no PTR |
.MODEL. Causes internal use32. |32-bit |DWORD |if <DWORD or >DWORD requires PTR|
|user supplied | condition
| values |
| reg | size |
.386 instruction or greater is |8-bit | BYTE |can only use BYTE, no PTR |
before compact,large,or huge |16-bit | WORD |can only use WORD, no PTR |
.MODEL. Causes internal use32. |32-bit |DWORD |if <DWORD or >DWORD requires PTR|
Cases where cpu instruction is AFTER .MODEL
|user supplied | condition
| values |
| reg | size |
.286 instruction or less is |8-bit | BYTE |can only use BYTE, no PTR |
after tiny,small or medium |16-bit | WORD |if <WORD or >WORD requires PTR|
.MODEL. Causes internal use16.
|user supplied | condition
| values |
| reg | size |
.286 instruction or less is |8-bit | BYTE |can only use BYTE, no PTR |
after compact,large,or huge |16-bit | WORD |can only use WORD, no PTR |
.MODEL. Causes internal use16.
|user supplied | condition
| values |
| reg | size |
.386 instruction or greater is |8-bit | BYTE |can only use BYTE, no PTR |
after tiny,small or medium |16-bit | WORD |if <WORD or >WORD requires PTR|
.MODEL. Causes internal use16. |32-bit |DWORD |can only use DWORD, no PTR |
|user supplied | condition
| values |
| reg | size |
.386 instruction or greater is |8-bit | BYTE |can only use BYTE, no PTR |
after compact,large,or huge |16-bit | WORD |can only use WORD, no PTR |
.MODEL. Causes internal use16. |32-bit |DWORD |if <DWORD or >DWORD requires PTR|
THIS IS THE WAY IT SHOULD BE:
|user supplied | condition
| values |
| reg | size |
.286 instruction or less is |8-bit | BYTE |can only use BYTE, no PTR |
before any .MODEL instruction |16-bit | WORD |if <WORD or >WORD requires PTR|
or no cpu instruction before
.MODEL. Causes internal use16.
|user supplied | condition
| values |
| reg | size |
.386 instruction or greater is |8-bit | BYTE |can only use BYTE, no PTR |
before any .MODEL instruction. |16-bit | WORD |if <WORD or >WORD requires PTR |
Causes internal use32. |32-bit |DWORD |if <DWORD or >DWORD requires PTR|
|user supplied | condition
| values |
| reg | size |
.286 instruction or less is |8-bit | BYTE |can only use BYTE, no PTR |
after any .MODEL instruction |16-bit | WORD |if <WORD or >WORD requires PTR|
Causes internal use16.
|user supplied | condition
| values |
| reg | size |
.386 instruction or greater is |8-bit | BYTE |can only use BYTE, no PTR |
after any .MODEL instruction. |16-bit | WORD |if <WORD or >WORD requires PTR |
Causes internal use16. |32-bit |DWORD |if <DWORD or >DWORD requires PTR|
答案 3 :(得分:0)
迈克尔:
以下是创建16位代码的代码示例:
.Model small,c ;since cpu instruction is after .Model it causes USE16 to be used
.286
.code
assume bx:word
call bx
end
由于use16实际上有效,因此会创建一个16位的段,.286告诉它使用16位的指令。汇编完以上代码后,它将为Call bx指令创建操作码FF D3。指令“调用NEAR PTR bx”或“调用NEAR16 PTR bx”也创建相同的操作码。
这是另一个创建32位代码的代码示例:
.Model small,c ;since cpu instruction is after .Model it causes USE16 to be used
.386
.code
assume ebx:dword
call ebx
end
由于use16实际上有效,因此会创建一个16位的段,.386告诉它使用32位的指令。汇编完以上代码后,它将为Call ebx指令创建操作码66 FF D3。指令“调用NEAR PTR ebx”或“调用NEAR32 PTR ebx”或“调用FAR16 ptr ebx”也创建相同的操作码。汇编器识别出在16位段中使用了386条指令,这导致汇编器在插入之前 每条386指令以66进制表示。请注意,用于16位和32位的操作码是相同的,唯一的区别是前缀操作码在那里。如果创建了32位段并且正在使用16位指令,则将相同的66十六进制前缀代码放在16位操作码之前。请注意,前缀字节是否存在唯一的区别。仅当段使用大小(use16或use32)与cpu指令大小(16位或32位)不匹配时,才放置前缀操作码(66)。对于使用16位或32位寄存器的ASSUME,规则应相同,但它们不在MASM中。
答案 4 :(得分:-1)
What is the purpose of MASM Assume Directive是ASSUME指令用法的出色摘要。回顾过去,也经常看到它用于指定段寄存器列表。在现代处理器上,这种用法已经过时了。