从有符号/无符号字符到无符号/有符号整数类型转换的 IA32 汇编代码
Posted
技术标签:
【中文标题】从有符号/无符号字符到无符号/有符号整数类型转换的 IA32 汇编代码【英文标题】:IA32 Assembly code for type casting from signed/unsigned char to unsigned/signed int 【发布时间】:2020-06-11 06:28:48 【问题描述】:这是从计算机系统,程序员的角度来看(第 2 版)
在问题 3.4 中,要求学生确定从源数据类型转换到指针所指的目标所需的汇编指令
本章后面给出的这个答案表明我们需要将源类型(左列)扩展为目标类型(中列)。
没有太多信息可以从这个问题中得出一个模式。扩展的类型是否总是由源类型而不是目标类型决定,如本例所示?
【问题讨论】:
这是什么语言?我所知道的同时拥有char
和unsigned char
的唯一HLL 是C 和C++,这对那些人来说是错误的。对于 most 中的整数类型,x
是有符号的,unsigned x
是无符号的(可能在位域中使用时除外),但对于 char
,符号是依赖于实现的,这意味着(如标准)它可能会有所不同,但必须记录在案。 C的这部分是由C++复制的。
教科书只使用C
【参考方案1】:
答案就在你的书中。
执行同时涉及大小更改和更改的演员表时 对于 C 中的“签名”,操作应首先更改大小。 (第 2.2.6 节)。
-- CSAPP 2e,练习题 3.4
所以这两个转换是这样工作的:
char --> int --> unsigned int
unsigned char --> unsigned int --> int
【讨论】:
在 C 中,由于 整数提升 规则会发生大小变化,然后应用转换。所以,首先unsigned char --> int
然后应用演员表。将unsigned char
扩大到int
意味着零扩展,以便表示更广泛的int
类型中的所有值。【参考方案2】:
扩展的类型是否总是由源类型而不是目标类型决定,就像这个例子一样?
是的。
强制转换保留由原始位表示的 值(如果可能)。规则由此而来,因此这是让您思考为什么其他所有内容的关键概念就是这样。
如果它是无符号的,您可以通过在左侧填充零来使其更宽。 (零扩展名:movzx
,AT&T movzbl
/ movzwl
/ movl
(x86-64 上的 dword 到 qword))
如果已签名,您可以通过填充符号位的副本来使其更宽。
(2's complement sign extension1:movsx
,或 AT&T movsbl
/ movswl
/ movsb/wq
)
对于任何值,只需截断即可使其变窄
(从内存中读取低字节,或者更窄的部分寄存器)
做任何其他事情都不会保值。例如对于窄无符号 -> 宽有符号,宽类型可以表示窄类型的所有可能值。结果必须是非负的,因此符号位必须为零。 除了符号位,2 的补码和无符号二进制位值是相同的。 所以零扩展有效。例如192
作为 uint8_t
与 192
作为 int
相同,但在 int
的左侧有更多的零位。
根据 ISO C11 (n1570),转换规则非常合理,并且与您的教科书显示的内容相匹配:
6.3 转化
6.3.1.3 有符号和无符号整数
当整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新类型表示,则 没有改变。 否则,如果新类型是无符号的,则通过重复加或减一的最大值来转换该值 可以用新类型表示,直到值在 新类型.60) 否则,新类型是有符号的,值不能在其中表示;结果是实现定义的或 引发了实现定义的信号。
对于第 2 点,请注意“就好像通过重复加或减 MAX_INT 一样”(对于 2 的补码)等同于简单地将位模式重新解释为有符号。即将 int 转换为 unsigned 不需要 asm 操作,您只需 mov
或更好地读取该值已经存在的任何寄存器或内存。
更多细节:无符号类型不能表示负值,因此这是一种情况,即使负输入更窄,它也不能为负输入“保值”。您可以将其视为逻辑符号扩展为等宽有符号类型(可以表示值),然后转换为无符号(只是重新解释相同的位,即扩大转换后没有额外的 asm 指令)。
脚注 1:x86 使用 2 的补码,其他所有相关内容也是如此。 C++ 甚至考虑放弃使用符号/幅度或 1 的补码整数的实现选项。
另请注意,教科书的答案使用了movz/sbl
的不可编码形式。它们仅适用于注册目的地。 movzbl %al, %ebx
可以,movzbl (%esi), %ebx
也可以,但movzbl %al, (%ebx)
不是可以的。
也相关:
https://www.felixcloutier.com/x86/movzx / * https://www.felixcloutier.com/x86/movsx MOVZX missing 32 bit register to 64 bit register What does cltq do in assembly? - Intel 与 AT&Tmovsb/w
的等效表,以及特殊情况 AX->EAX 和类似指令。
【讨论】:
以上是关于从有符号/无符号字符到无符号/有符号整数类型转换的 IA32 汇编代码的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Rust 中将有符号整数添加到无符号整数,检查无符号溢出?