登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

仙剑奇侠传的博客

羽化成仙

 
 
 

日志

 
 

X86汇编之七(使用数字)  

2011-08-20 23:40:00|  分类: 汇编 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

关键字:movsx movzx movq

本文参考如下:Richard BlumProfessional Assembly Language

一、数字类型:

1、基本数字类型:

intel系列cpu支持以下数据类型:

Unsigned integers

Signed integers

Binary-coded decimal

Packed Binary-coded decimal

Single-precision floating-point

Double-precision floating-point

Double-extended floating-point

2、在奔腾以上处理器增加了增加一些高级数字类型:

64-bit packed integers

128-bit packed integers

128-bit packed single-precision floating-point

128-bit packed double-precision floating-point

二、Integers

1、Standard integers

gas中,整型是常用的一个数据类型,有以下基本整型:

Byte:8 bits

Word:16 bits

Doubleword :32 bits

Quadword :64 bits

不是byte的整型其数据在内存中与寄存器的字节顺序有所不同,在内存中intel系列cpu是little-endian格式进行存放,在寄存器中是采用big-endian格式进行数据存放。如图所示:

cpu隐式处理在内存中的字节顺序与寄存器的字节顺序的转换

示例:endiantest.s

1)代码

/*********************************

本程序查看内存变量与寄存器变量

用gdb的x/x x/4b这样的方式查看内存变量与寄存器

*************************************/

.section .data

output:

.long 0x3276

.section .text

.globl _start

_start:

nop;

movl output,%eax

movl $1,%eax

2)、编译连接调试

as -o endiantest.o endiantest.s -gstabs

ld -o endiantest.exe endiantest.o

gdb -q endiantest.exe

 

调试过程如下:

(gdb) x/x &output

0x402000 <output>: 0x00003276

(gdb) x/4b &output

0x402000 <output>: 0x76 0x32 0x00 0x00

从调试结果看到,低位值放到了低内存

2、整型数表示范围

位数

无符号

有符号

8 bits

0~28-1

-28-1~28-1 -1

0~255

-128~127

16 bits

0~216-1

-216-1~216-1 -1

0~65535

-32768~32767

32 bits

0~232-1

-232-1~232-1 -1

0 ~4294967295

-2147483648~2147483647

64 bits

0~264-1

-264-1~264-1 -1

  

 

3、Using Signed Integrs

有符号数扩展失真的问题,寄存器有8位、16位、32位之分,如16分的有符号数在16位寄存器中传递给32位寄存器,到了32位寄存器就其值就会发生变化。汇编语言默认的寄存器中的数为有符号数。如al中的值为:0xFF,打印出来应该是-1而不是255.

/*********************************

测试把16位值移到32位值,看其变化

*************************************/

.section .data

value:

.byte 0xff

value2:

.short 0xffbe #值为-66

.section .text

.globl _start

_start:

nop;

movw value,%bx

movw value2,%cx

movl $1,%eax

ret

通过gdb调试得到结果如下:

(gdb) n

13 movw value,%bx

(gdb) n

14 movw value2,%cx

(gdb) n

15 movl $1,%eax

(gdb) info reg

eax 0x76141182 1981026690

ecx 0xffbe 65470

edx 0x401000 4198400

ebx 0x7ffdbeff 2147335935

esp 0x22ff8c 0x22ff8c

ebp 0x22ff94 0x22ff94

esi 0x0 0

edi 0x0 0

eip 0x40100f 0x40100f <start+15>

eflags 0x246 [ PF ZF IF ]

cs 0x1b 27

ss 0x23 35

ds 0x23 35

es 0x23 35

fs 0x3b 59

gs 0x0 0

(gdb) x/dh &value2

0x402001 <value2>: -66

ecx寄待的值是-66,但显示出了65470。这表示把16位数拓展到32位数,数据发生的失真

4、使用movsx指令(有符号扩展赋值指令)。

movsx指令用来把8位、16位进行符号扩展后把值赋值给16位、32位寄存器或内存。通过movsx能确保数据传递的正确。movsx有符号展

# movsxtest.s -an example of MOVSX instruction

.section .text

.globl _start

_start:

nop

movw $-79,%cx

movl $0,%ebx

movw %cx,%bx

movsx %cx,%eax

movl $1,eax

ret

 

gdb调试如下:

(gdb) info reg

eax 0xffffffb1 -79

ecx 0xffb1 65457

edx 0x401000 4198400

ebx 0xffb1 65457

esp 0x22ff8c 0x22ff8c

ebp 0x22ff94 0x22ff94

esi 0x0 0

从输出看 movsx指,到高位中的用当前数的最高位进行填,如当前位为1就是1,所0xffb1(-79)从cx到eax成了(0xffffffb1)

5、使用无符号扩展指令movzx.

movzx指令用来把8位、16位数扩展转换成16位、32位。movzx,数成正数了。

# movzxtest.s -an example of MOVZX instruction

.section .text

.globl _start

_start:

nop

movw $-79,%cx

movl $0,%ebx

movw %cx,%bx

movzx %cx,%eax

movl $1,%eax

ret

gdb调试输出信息如下:

(gdb) info reg

eax 0xffb1 65457

ecx 0xffb1 65457

edx 0x401000 4198400

ebx 0xffb1 65457

esp 0x22ff8c 0x22ff8c

ebp 0x22ff94 0x22ff94

 

6、8字节整型。c语言中有long long这个数据类型。这个类型的汇编实现为:

.globl _a

    .data

    .align 8

_a:

    .long    -1

    .long    2147483647

解释如下:.align 8指示其对齐地址按照8的倍数进行,8个字节用2个long类型表示,按照little-endian,第一个.long存64位整数的低位

  评论这张
 
阅读(384)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018