- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试了解GAS的.code16
行为。
在手册中,对于16位部分,对于32位操作数或指令,似乎会为指令编码生成一个66H操作数替代前缀。这是否意味着
.code16
movw %eax, %ebx
在这种模式下合法吗?那么代码不能在16位处理器上运行吗?
最佳答案
这些是80386+的法律说明。
Starting with the 80386 we can use
operandsize-
andaddresssize-
override prefixes. Those prefixes can be used in combination with the 16 bit address mode and with the 32-bit address mode.Additional it can be used with the real address mode and with the protected mode and the virtual 86 mode. Those prefixes reverse the default operand size and/or the address size for one instruction in the code segment. The default operand size and the address size is specified by the D flag in the code-segment descriptor (or if there is no GDT/LDT, then we become the 16 bit address mode after the POST-process of the bios is done.)
With the 16 bit address mode we have to add those prefixes, if we want to use 32-bit operands and/or 32-bit addresses. Without those prefixes we can only use 16-bit addresses/operands in the 16-bit address mode.
With the 32-bit address mode we have to leave out those prefixes from our code, if we want to use 32-bit operands and/or 32-bit addresses. And if we add those prefixes to our code, then we can use 16-bit addresses/operands in the 32-bit address mode.
Instruction prefixes can be used to override the default operand size and address size of a code segment. These prefixes can be used in real-address mode as well as in protected mode and virtual-8086 mode. An operand-size or address-size prefix only changes the size for the duration of the instruction.
The following two instruction prefixes allow mixing of 32-bit and 16-bit operations within one segment:
- The operand-size prefix (66H)
- The address-size prefix (67H)
These prefixes reverse the default size selected by the D flag in the code-segment descriptor. For example, the processor can interpret the (MOV mem, reg) instruction in any of four ways:
In a 32-bit code segment:
- Moves 32 bits from a 32-bit register to memory using a 32-bit effective address.
- If preceded by an operand-size prefix, moves 16 bits from a 16-bit register to memory using a 32-bit effective address.
- If preceded by an address-size prefix, moves 32 bits from a 32-bit register to memory using a 16-bit effective address.
- If preceded by both an address-size prefix and an operand-size prefix, moves 16 bits from a 16-bit register to memory using a 16-bit effective address.
In a 16-bit code segment:
- Moves 16 bits from a 16-bit register to memory using a 16-bit effective address.
- If preceded by an operand-size prefix, moves 32 bits from a 32-bit register to memory using a 16-bit effective address.
- If preceded by an address-size prefix, moves 16 bits from a 16-bit register to memory using a 32-bit effective address.
- If preceded by both an address-size prefix and an operand-size prefix, moves 32 bits from a 32-bit register to memory using a 32-bit effective address.
The previous examples show that any instruction can generate any combination of operand size and address size regardless of whether the instruction is in a 16- or 32-bit segment. The choice of the 16- or 32-bit default for a code segment is normally based on the following criteria:
- Performance — Always use 32-bit code segments when possible. They run much faster than 16-bit code segments on P6 family processors, and somewhat faster on earlier IA-32 processors.
- The operating system the code segment will be running on — If the operating system is a 16-bit operating system, it may not support 32-bit program modules.
- Mode of operation — If the code segment is being designed to run in real-address mode, virtual-8086 mode, or SMM, it must be a 16-bit code segment.
- Backward compatibility to earlier IA-32 processors — If a code segment must be able to run on an Intel 8086 or Intel 286 processor, it must be a 16-bit code segment.
The D flag in a code-segment descriptor determines the default operand-size and address-size for the instructions of a code segment. (In real-address mode and virtual-8086 mode, which do not use segment descriptors, the default is 16 bits.) A code segment with its D flag set is a 32-bit segment; a code segment with its D flag clear is a 16-bit segment.
Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can be used to select an operand size other than the default, and the prefix 67H can be used select an address size other than the default.
The 32-bit operand prefix can be used in real-address mode programs to execute the 32-bit forms of instructions. This prefix also allows real-address mode programs to use the processor’s 32-bit general-purpose registers.The 32-bit address prefix can be used in real-address mode programs, allowing 32-bit offsets.
The IA-32 processors beginning with the Intel386 processor can generate 32-bit offsets using an address override prefix; however, in real-address mode, the value of a 32-bit offset may not exceed FFFFH without causing an exception.
Assembler Usage:
If a code segment that is going to run in real-address mode is defined, it must be set to a USE 16 attribute. If a 32-bit operand is used in an instruction in this code segment (for example, MOV EAX, EBX), the assembler automatically generates an operand prefix for the instruction that forces the processor to execute a 32-bit operation, even though its default code-segment attribute is 16-bit.
The 32-bit operand prefix allows a real-address mode program to use the 32-bit general-purpose registers (EAX, EBX, ECX, EDX, ESP, EBP, ESI, and EDI).
When moving data in 32-bit mode between a segment register and a 32-bit general-purpose register, the Pentium Pro processor does not require the use of a 16-bit operand size prefix; however, some assemblers do require this prefix. The processor assumes that the 16 least-significant bits of the general-purpose register are the destination or source operand. When moving a value from a segment selector to a 32-bit register, the processor fills the two high-order bytes of the register with zeros.
3.3.2. 32-Bit vs. 16-Bit Address and Operand Sizes
The processor can be configured for 32-bit or 16-bit address and operand sizes. With 32-bit address and operand sizes, the maximum linear address or segment offset is FFFFFFFFH (2^32-1), and operand sizes are typically 8 bits or 32 bits. With 16-bit address and operand sizes, the maximum linear address or segment offset is FFFFH (2^16-1), and operand sizes are typically 8 bits or 16 bits.
When using 32-bit addressing, a logical address (or far pointer) consists of a 16-bit segment selector and a 32-bit offset; when using 16-bit addressing, it consists of a 16-bit segment selector and a 16-bit offset. Instruction prefixes allow temporary overrides of the default address and/or operand sizes fromwithin a program.
When operating in protected mode, the segment descriptor for the currently executing code segment defines the default address and operand size. A segment descriptor is a system data structure not normally visible to application code. Assembler directives allow the default addressing and operand size to be chosen for a program. The assembler and other tools then set up the segment descriptor for the code segment appropriately.
When operating in real-address mode, the default addressing and operand size is 16 bits. An address-size override can be used in real-address mode to enable 32-bit addressing; however, the maximum allowable 32-bit linear address is still 000FFFFFH (2^20-1).
3.6. OPERAND-SIZE AND ADDRESS-SIZE ATTRIBUTES
When the processor is executing in protected mode, every code segment has a default operand-size attribute and address-size attribute. These attributes are selected with the D (default size) flag in the segment descriptor for the code segment (see Chapter 3, Protected-Mode Memory Management, in the Intel Architecture Software Developer’s Manual, Volume 3). When the D flag is set, the 32-bit operand-size and address-size attributes are selected; when the flag is clear, the 16-bit size attributes are selected. When the processor is executing in real-address mode, virtual-8086 mode, or SMM (System-Management-Mode), the default operand-size and address-size attributes are always 16 bits.
The operand-size attribute selects the sizes of operands that instructions operate on. When the 16-bit operand-size attribute is in force, operands can generally be either 8 bits or 16 bits, and when the 32-bit operand-size attribute is in force, operands can generally be 8 bits or 32 bits.
The address-size attribute selects the sizes of addresses used to address memory: 16 bits or 32 bits. When the 16-bit address-size attribute is in force, segment offsets and displacements are 16 bits. This restriction limits the size of a segment that can be addressed to 64 KBytes. When the 32-bit address-size attribute is in force, segment offsets and displacements are 32 bits, allowing segments of up to 4 GBytes to be addressed.
The default operand-size attribute and/or address-size attribute can be overridden for a particular instruction by adding an operand-size and/or address-size prefix to an instruction (see “Instruction Prefixes” in Chapter 2 of the Intel Architecture Software Developer’s Manual, Volume 3). The effect of this prefix applies only to the instruction it is attached to.
Table 3-1 shows effective operand size and address size (when executing in protected mode) depending on the settings of the D flag and the operand-size and address-size prefixes.
关于overriding - 16位模式下的操作数大小前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13173138/
int enter_path(char** path) { char* standard = "./questions.txt"; printf("\n\t%s\n\t%s",
我有以下几行代码: #define PORT 9987 和 char *ptr = (char *)&PORT; 这似乎适用于我的服务器代码。但是当我在我的客户端代码中写它时,它给出了这个错误信息:
大家好,我在成员函数中有以下内容 int tt = 6; vector>& temp = m_egressCandidatesByDestAndOtMode[tt]; set& egressCandi
我知道您可以通过以下方式在正则表达式中使用 NOT 操作数: [^AB] :匹配除 "A" 之外的任何内容或"B" A(?!B) :匹配"A" ,后面不跟 "B" (?
我的代码如下,下面还解释了为什么会发生左值; typedef struct test_item { char id[MENU_NAME_LEN + NULL_SPACE]; MenuF
我正在审查一些 javascript 代码,程序员在几个地方使用了 >>。我试图在谷歌上搜索但找不到这个操作数/运算符的作用。所以我来了。下面的代码示例: var triplet=(((binarra
我使用以下行(希望这是最佳实践,如果不正确请纠正我)来处理命令行选项: #!/usr/bin/bash read -r -d '' HELP &2 for i in "${invalid_opti
我正在尝试编辑一个计时器应用程序,出现了这行代码。我该如何解决? let styleMask: Int = NSClosableWindowMask | NSTitledWindowMask 错误是:
我可以得到两个特定日期之间的差异,这将等于日期总数。现在我想将工作日除以总天数并得到整数输出。 @IBAction func go(_ sender: UIButton) { let con
我的项目有一个问题,它应该使用一个线程将每一行相加,然后将它们全部相加,但是我收到一个错误,指出左值需要作为一元 '&"操作数 pthread_create(&tid, NULL, &sum_line
我的代码有问题。有以下功能: static Poly PolyFromCoeff(int coeff); static Mono MonoFromPoly(const Poly *p, int exp
在 C# 中是否没有字符串的 OR 操作数? 我正在查看 Microsoft C# 操作数页面 - 没有关于字符串的任何类型的 OR。 我有一个要写的 if 语句: if (Convert.ToStr
下面的函数左移一个double操作数: double shl(double x,unsigned long long n) { unsigned long long* p = (unsigne
我在 Linux 中使用了以下简单的 ksh 脚本 #!/bin/ksh set -x ### Process list of *.dat files if [ -f *.dat ] then pri
我有一个使用 Entity Framework 的查询。它有许多不同的操作数,我对其优先级感到困惑。我得到了错误的结果。我需要所有 IsPaid == true 或 IsPaid == null 的记
我有以下代码来尝试创建一个约束数组以添加到 View 中: let views = ["button": button] let metrics = ["margin": 16] var constr
这个问题在这里已经有了答案: How to compare one value against multiple values - Swift (8 个答案) 关闭 6 年前。 我有一种情况,我必须
我使用 jquery $.ajax 将请求发送到服务器,它返回 JSON。 $.ajax({ url: 'moreMonth.ajax', data: { startIndex: id },
我的问题是程序没有按照“他”的预期读取代码。 我有 if (hero.getPos() == (6 | 11 | 16)) { move = new Object[] {"Up", "Righ
我在对象中创建线程时遇到问题。错误是需要作为一元“&”操作数的左值 CPP文件 #include "AirQ.h" static int i=0; AirQ::AirQ(int pinNo, bool
我是一名优秀的程序员,十分优秀!