使用masm的ASSUME指令

时间:2019-05-25 05:56:33

标签: assembly x86 masm x86-16 memory-segmentation

我一直在尝试使用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]中。请注意,执行相同操作的指令没有假设。

5 个答案:

答案 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位。
因此,.386ASSUME 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指令用法的出色摘要。回顾过去,也经常看到它用于指定段寄存器列表。在现代处理器上,这种用法已经过时了。