表示数字和使用数字是汇编语言的重要部分
核心的数字类型有几种
Unsigned integers
Signed integers
Binary-coded decimal
Packed binary-coded decimal
Single-precision floating-point
Double-precision floating-point
Double-extended floating-point
除了基础的数字类型,在奔腾处理器上SIMD extensions增加一些更高级的数字类型
64-bit packed integers
128-bit packed integers
128-bit packed single-precision floating-point
128-bit packed double-precision floating-point
在汇编当中最基本的就是整型.
Byte: 8 bits
Word: 16 bits
Doubleword: 32 bits
Quadword: 64 bits
理解存储在内存当中高于一个字节的整数,是按小端存储的。这代表着最低位的字节存储在最低位字节的内存位置,剩下的高位字节紧随其后. 但是当整型数据移动到寄存器的时候,是按大端存储的,这个时候就有些令人困惑了. 这种转化对于用户来说是透明的,所以也不需要特别的担心,但是当你调试程序的时候发现下面的情况,不要慌张.
(gdb) x/x &data
0x80490bc <data>: 0x00000225
(gdb) x/4b &data
0x80490bc <data>: 0x25 0x02 0x00 0x00
(gdb) print/x $rax
$1 = 0x225
(gdb)
//TODO:64位估计不是x/4b 猜是x/8b,以后再验证 十进制数549存储在内存的data处,然后移动到RAX寄存器.第一条gdb指令显示的是在data处十六进制的内容.第二条指令显示4个用来构成这个字节的内存,这就是小端的形式.
注意前方高能,需要脑补机组的知识
无符号整数就是一种你看到是多少就是多少的类型("what you see is what you get").构成数字的字节直接用来表示这个数. 相应无符号整数的范围
Bits Integer Values
8 0 through 255
16 0 through 65,535
32 0 through 4,294,967,295
64 0 through 18,446,744,073,709,551,615
以后举例子几个类型内存的的表示,基本上大同小异.
有三种方法表示符号数分别是
Signed magnitude
One’s complement
Two’s complement
有首位表示正负,但是会有+0和-0出现,而且不能通过直接加减得到对应的答案.
传说中的反码表示,把对应位取反,比如00000001对应的是1111110,这样的方式还是有问题,具体以后解释.
传说中的补码表示,负数取反加1,正数不变就是补码.这样的好处是加减的时候得到的补码能够正确反应结果.
# inttest.s - An example of using signed integers
.section .data
data:
.int -45
.section .text
.globl _start
_start:
nop
movl $-345, %ecx
movw $0xffb1, %dx
movl data, %ebx
mov $60, %rax
syscall
//TODO:改成64位的寄存器 这些都是使用数字的方法,但是不同的是我们通过调试的时候会有如下情况
(gdb) info reg
eax 0x0 0
ecx 0xfffffea7 -345
edx 0xffb1 65457
ebx 0xffffffd3 -45
数字都是存对了,但是edx之所以是那个数是因为将edx整个看作一个数了,而不是取dx的那几位. 所以寄存器在分辨数字的时候也是挺令人困惑的.
有时候你需要将word大的数字放到doubleword大的地方,这看起来很容易,但实际上有点困难.
向大尺寸移动的时候要确保高位都被设为0.例如movw %ax,%bx
这个不能保证正确,你应该将高位清零.
movl $0, %ebx
movw %ax, %ebx
这样才能保证移动是正确的. 但是有一个MOVZX指令可以帮你完成这件事高位清零的事.当然使用的时候也要注意源寄存器的大小,以免没有完全复制.
扩展有符号数又不简单了,因为有符号数的-1(11111111)如果要扩展到doubleword会变成000000001111111,这个数是127而不是-1了. 所以对于有符号数来说增加的位需要为1.
Intel提供了MOVSX指令允许有扩展有符号数并且保持符号不变。这有点像MOVZX但是假设操作数的是有符号的数. //TODO:补充一个例子
在第五章当中提到的.int,.short,.long命令都是用来定义整型数字的.还可以用.quad来定义quadword有符号数. //TODO:这个似乎32和64有点区别,以后更
The Intel Single Instruction Mutiple Data技术能够提供额外的方法使用整型.//TODO:给个简单的解释
The Multimedia Extension technology 提供3个整型类型:
64-bit packed byte integers
64-bit packed word integers
64-bit packed doubleword integers
每个MMX寄存器可以容纳多个整型元素,如图,补个图 //TODO:加个图
# mmxtest.s - An example of using the MMX data types
.section .data
values1:
.int 1, -1
values2:
.byte 0x10, 0x05, 0xff, 0x32, 0x47, 0xe4, 0x00, 0x01
.section .text
.globl _start
_start:
nop
movq values1, %mm0
movq values2, %mm1
mov $60,%rax
syscall
//TODO:说明
The Streaming SIMD Extension(SSE)技术提供128bit的XMM寄存器.The SSE2 techonology(在奔腾4引入)提供额外的4个整数类型
128-bit packed byte integers
128-bit packed word integers
128-bit packed doubleword integers
128-bit packed quadword integers
//TODO:补充个图
依赖 MOVDQA和MOVDQU 命令.//TODO:补充例子和解释
The Binary Coded Decimal (BCD) 数据类型存在了很长的时间.
//TODO:解释
BCD 使用FPU寄存器来存储 //TODO:解释
依赖fbld source
命令,source是一个80bit内存的地址
#bcdtest.s - An example of using BCD integer values
.section .data
data1:
.byte 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
data2:
.int 2
.section .text
.globl _start
_start:
nop
fbld data1
fimul data2
fbstp data1
mov $60,%rax
syscall
//TODO:解释