当32位寄存器可以访问汇编时,DOS控制台数据存储器访问

时间:2018-02-12 19:44:25

标签: windows assembly memory dos tasm

我正在研究TASM程序集中的一个项目,当我在汇编程序中使用32位寄存器(.386)时,我在向DOS控制台的特定单元输出颜色时遇到问题。

以下是我通常会这样做的一个示例:

细胞的BX位点,
AH颜色/细胞炭

mov ah , 01000000b ; Color Red to ah
mov ax,0b800h ; memory location of the console 
mov es,ax ; to es 
mov es:[bx] , ah ; mov data from ah to the cell of bx 

这样可行,但是当我在开始时.386将其设为32位时,此代码停止工作......任何人都知道解决问题的方法吗?  简短: 代码需要将Color设置为单元格。在没有.386的情况下工作,并停止使用.386

代码段:

.386
.Model small
.data 
 ;all my data 
 .code 
  Start:
  ; all the code in there also the output code snippet I showed 
 end start 

通过Ped7g修复: 将行.386放在.code

玛格丽特布鲁姆修复: 将USE16修饰符添加到MODEL指令

两者都有效。谢谢你的帮助

TASM 32位

2 个答案:

答案 0 :(得分:5)

如果未明确指定代码段的属性,则使用.386指令会将默认操作数侧设置为32位。

引用TASM manual

  

请注意,您可以在两个位置指定模型修改器,以便与之兼容   MASM 5.2。如果你不使用模型说明符,Turbo Assembler as.sumes the   NEARSTACK修饰符和USE32(如果选择了80386或80486处理器)。

这并不意味着您可以使用32位寄存器 1 ,但汇编程序将以“镜面”方式发出指令。

x86计算机中的所有代码都具有默认操作数大小 当以32位运行时,它是32位,当以16位运行时,它是16位(64位更多涉及,它仍然是32位,但可以用REX.W前缀覆盖)。

默认操作数大小确定立即操作数的默认大小,即指示期望值的指令的操作码之后的字节数。

mov ax, 0b800hmov eax, 0b800h等说明采用相同的方式编码:使用操作码B8
在此操作码之后,它遵循16或32位的立即操作数 具体大小取决于默认操作数大小。

要访问“其他”大小,即在32位代码中指定16位版本的指令,反之亦然,则存在操作数大小覆盖前缀(值66)。

放桌子

                    +-----------------------------------------+
                    |           Default operand size          | 
+-------------------+---------------------+-------------------+ 
|Instruction        |      16             |        32         |
+-------------------+---------------------+-------------------+
|                   |                     |                   |
|mov ax, 1234h      |     B8 34 12        |    66 B8 34 12    |  
|                   |                     |                   |
|mov eax, 12345678h |  66 B8 78 56 34 12  |   B8 78 56 34 12  |   
|                   |                     |                   |
+-------------------+---------------------+-------------------+

当汇编程序假定默认操作数大小为32位时,查看mov ax, 0b800h如何用66 B8编码?
并且当以16位代码执行时,66 B8被解码具有32位立即数?

这搞砸了后续指令的解码。

组装为32位代码作为16位代码执行时发布的剪辑导致:

00000000  B440              mov ah,0x40
00000002  66B800B88EC0      mov eax,0xc08eb800
00000008  26678827          mov [es:edi],ah

如何解决此问题

明确地为每个代码段提供代码大小属性,或者使用MODEL指令设置默认值 例如,如果您使用SMALL内存模型:

.MODEL USE16 SMALL 

1 就CPU而言,你总是这样,只是TASM拒绝组装不符合所选处理器系列的指令。

答案 1 :(得分:2)

在使用x86保护模式(16位或32位变体)的任何可能性之前,必须运行某些机器指令组,将CPU从实模式转移到保护模式。这是一件非常简单的事情,因为您需要设置至少最少数量的系统表和系统寄存器,例如CR0。英特尔软件开发人员手册Volume 3中详细介绍了汇编程序中的示例。

请注意,之后处理器行为的所有内容都会发生变化:您作为汇编程序输入写入的指令将不再意味着它们的含义(因为默认操作数和地址大小可能已更改),但最重要的是内存地址没有更长的只是指向物理内存,而是通过分段和分页进行转换。甚至必须重新计算您的控制台地址,以确保您指向正确的物理地址。请注意,良好的旧DOS中断将不再起作用,因为它们被写入以实模式工作并且不期望保护模式;它只会挂起或重启。

也许你应该澄清你想要实现的目标,以及为什么现有的实模式代码不能满足你的需求。如果你的目标是学习,那么我建议你熟悉一下保护模式是什么,如何将CPU转移到它,以及如何为它编写程序。我估计第一点需要花费80%或者你的时间,第二点是15%,程序本身只花费5%或更少的时间。

相关问题