汇编语言中数组的长度如何计算

汇编语言中数组的长度如何计算,第1张

数组存放实际上是一片连续的空间,所有的n维数组存放的时候都是按照一位数组的格式存放的数组a[2][2]的存放方式是从a[0][0]开始,依次是a[0][1],a[1][0],a[1][1],他们的存放空间是连续的

在汇编语言中,就可以在数据段中按照这个次序存放,

dseg

segment

array1

a00,a01,a10,a11

dseg

ends

然后按照这个次序调用就可以了

LENGTH返回的是类型重复的次数 BX里是A的长度 也就是6DUP(重复6次)所以是6 而CX是B的长度 每个当然是1 length只在DUP前有意义 否则返回的就是1

mov bx,size a A的大小是26 BX=12

mov cx,size b B的大小是46 CX=24

SIZE=LENGTHTYPE

TYPE: DB 1; DW 2; DD 4;

这里开始熟悉汇编的指令格式

下图为X86版本的指令格式,X64的指令格式和X86差不多后面有需要的话再详细写

Istruction Prefixes : 可选项

默认二进制文件是前缀和内容混杂在一起只有机器才能识别区别

人工区分方法:

X86格式图已经给我们提示,有四个组,一次最多使用一个组

段前缀指令的作用: 修改使用段寄存器

不加提示默认使用DS

如果有栈寄存器的话会使用SS

push ebp是设置程序为X86位下的16位模式情况下运行

CPU是如何判断程序有关系:

CS中有一个DB位如果CS中DB位为0则16位1位32

现在默认的CPU模式是32位,所以汇编指令就算是使用epb(16位寄存器)最少也是32位

如何使用16位的

只需要在硬编码前面加上前缀 66:即可

效果如上面

当CPU使用32位模式选址方式就会使用32位进行

当DB位为0的时候16位,使用16位寻址方式,当DB为1的时候使用32位寻址方式

决定 硬编码长度是由( Opcode ModR/M SIB )决定。前缀指令只会影响到他自己。

然后,ModR/M 由Opcode决定 SIB由ModR/M决定

虽然这个是叫做One-byte但是都是从这个表里面展开的

由这个图例查找,55,push rbp/13

然后 0F-3F都有两个 *** 作符,前面的是Opcode,后面跟着是ModR/M

如果Opcode跟着 ModR/M的话就是变长,没有则定长

所有两个 *** 作符的就判定前面的是Opcode,ModR/M

这是要理解这个我们可以查询他相关的问题 *** 作符解释

在Intell白皮书里面有Codes for addressing method

可以查到 *** 作符大写解释

下面的Codes for Operand Type

有 *** 作符小写解释

例如大写E前面很明显的写了A ModR/M byte follows the opcode

表中寄存器带个r表示可以随着系统变化而变化,可以是64位的RAX,也可以是32位的EAX,也可以是AX 表中会显示最大的修改位数,带E开头的表示只能修改32位和16位

ERX=EAX or ECX or EDX 等通用寄存器

硬编码 4开头是 INC/DEC 5开头的是push/pop

0-7是 INC PUSH

8-F是DEC POP

40开头的都两行格式,上面的一行表示32位,下面的是64位的。

在b开头的是mov指令

他的写法又不一样,mov AL\R8L,Ib

这样能够很好的解释定长指令不是只有一个字节

I是Immedlate立即数

b是bate 字节

v是 word doubleword quadword三种情况之一,他取决于你采用数据宽度

所以:

0-7 是 mov rb,lb

8-F 是 mov ERX,Iv

9开头 就是XCHG指令是两个寄存器之间交换而且都是放到EAX中

例:

但0是表示EAX 用EAX放到EAX中所以汇编中把

90作为nop 不做任何 *** 作。

我们通常使用Nop的时候是遇到花指令这个下次有时间再写。

90-97是有规则的,但8-F单独说

表格中如果带有

I64 指令表示这个指令在64位下单独表示,例如INC和DEC

o64 只能在64位系统下使用。

d64 这个指令默认是64位,且不支持32位

f64 在64位 *** 作系统下强制使用64位宽度

能够修改EIP的指令有JCC,call,ret三类

从上表中可以查到JCC的指令可以从 0x70~0x7F,八个指令。

上图是JCC指令示例

不论是70-7F中哪一个都会带有一个字节的数据,那个数据被称为偏移地址。

所以JCC普通跳转地址最大位一个字节(FF/2),80以下往下跳转,80以上往上跳转

条件跳转,后面跟一个字节立即数的偏移(有符号),共两个字节

如果条件成立调到当前指令地址+当前指令长度+LB

最大值:向前跳转7F,向后跳转80

而且当你要跳转的字节超过一个字节就会跳转到两个字节,

0F80 者就是两个字节,0F上会让你去看两字节的表同样书中会有这个表格

因为E指令有多个指令包含JMP,CALL,LOOP

J是 带偏移地址

上面的是常用的不常用的先不写了

MODR/M 只占一个字节八个位拆开就是下面:

经典的边长指令:

G(寄存器)是由ModR/M 中3,4,5位Reg/Opcode 决定的表格如下

E(寄存器)是由ModR/M中的0,1,2,6,7位Mod和R/M共同决定的:

注:

现在我们查一下一些不常用的指令的指令

0x80~0x83 首先是Imediate Grp 1^1A

1A的意思是下面的表格

1A就是 3,4,5不再代表通用寄存器,而是通用寄存器

所有的带有这些角标的都可以看扩展

Grp 1是下面的表格

具体的所有变长指令的表基本介绍完了,我们试试查找一下

81 22 08 FF

81 Ev,Iz

72 拆成字节是

0111 0010

根据ModR/M

01 110 010

结合 81 MOD 和 R/M 三个可以查出

XXX WORD ptr ds:[EDP+disp8],[immediate]

再用 reg查完整的就是

XOR WORD PTR DS:[EDP+disp8],Iz

这里还有两个未知数不知道 就是后面的数据

disp8是08 Iz就是FF

上面有提过:

当查ModR/M表查到--时,就表示ModR/M不能完全确定寄存器需要再跟一个字节来确定,这个字节就是SIB

例如:

88 84 48

Mov [--][--]+disp32,AL

SIB计算是这下面计算的

然后根据上面的数据可以查出

48

0100 1000

01 001 000

base 000 index 001 Scale 01

硬编码整个过程来说,就是简略的通过查表了解CPU将数据转化成汇编指令的过程。

看你用哪种汇编语言了,NASM中是

message db 'hello, world'

msglen equ $-message

$:当前语句的地址

NASM中变量和标签是一样的

应该没有直接的指令吧。要是有的话,它需要两个 *** 作数,一个是字符串的首字符的地址,一个是末字符的地址,那么它不就是减法指令吗。

那就要看cpu怎么识别机器码了,

比如

mov

al,00

的机器码是

1011

0000

0000

0000b

(b000h)

mov

的机器码是

1011

al

的机器码是

0000

cpu读取一条指令,假如第一个字节是b0,那么

就是mov

al,后面紧跟着的一个字节就是要传进去的立即数(cpu判定这条指令长度2个字节)

再者

mov

al,[0000]

的机器码是

1010

0000

(后面16位0)

如果这个字节是a0,那么就是寄存器间接寻址的mov

al,后面紧跟着的16位就是地址偏移量

(cpu就判定这条指令长度3个字节)

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

写好后用debug反汇编,u命令

1814:0000

33c0

xor

ax,ax

1814:0002

a08000

mov

al,[0080]

其中的

33c0

a08000

等就是指令的机器码

就看出来占几个字节了

那几个都是数值回送 *** 作符。这些 *** 作符把一些特征或存储器地址的一部分作为数值回送。(1)TYPE格式:TYPE expression如果该表达式是变量,则汇编程序将回送该变量的以字节数表示的类型:DB(字节)为1,DW(字)为2,DD(双字)为4,DF(六字节的字)为6,DQ(4字)为8,DT(10个字节)为10。如果表达式是标号,则汇编程序将回送代表该标号类型的数值:NEAR为-1,FAR为-2。如果表达式为常数,则应回送0。例: 定义了字符串 ARRAY DW 1,2,3 对于指令 ADD SI,TYPE ARRAY汇编程序将其形成为 ADD SI,2 (因为上面定义了DW类型)(2)LENGTH格式为:LENGTH variable①对于变量中使用DUP的情况,汇编程序将回送分配给该变量的单元数②对于其他情况则送1例1: 定义 FEES DW 100 DUP(0) -----分配给FEES 100个单元对于指令 MOV CX,LENGTH FEES汇编程序将使其形成为 : MOV CX,100 例2: 定义 ARRAY DW 1,2,3对于 MOV CX,LENGTH ARRAY汇编将使其形成为: MOVCX,1 例3: TABLE DB ‘ABCD’对于指令 MOV CX,LENGTH TABLE形成为 MOV CX,1(3)SIZE格式:SIZE variable汇编程序回送分配给该变量的字节数。次值是LENGTH值和TYPE值的乘积。例①: 定义 FEES DW 100 DUP(0) -----分配给FEES 100个单元对于指令 MOV CX,SIZE FEES汇编程序将使其形成为 : MOV CX,200 例2:定义 ARRAY DW 1,2,3对于 MOV CX,SIZE ARRAY汇编将使其形成为: MOVCX,2 例3: TABLE DB ‘ABCD’对于指令 MOV CX,SIZE TABLE形成为 MOV CX,1

因为2000:0003处的指令 MOV BX,0003H的指令代码占3个字节,所以,读取完该指令后,指令缓冲器的内容为该指令机器代码:BB 03 00。当然,读取得这3个字节的指令并不是一次访存完成的,至少要通过两次访存,第一次读取字节BB,第二次读取16字03 00。

CPU读取指令时,如果单字节指令,一次访存即可完成读取 *** 作;如果是多字节指令,会根据第一次读取指令的 *** 作码与寻址标志位,判断指令的后续长度,进而完成整个指令的读取,同时指令指针IP会自动进行修改,指向下一条待取指令。

以上就是关于汇编语言中数组的长度如何计算全部的内容,包括:汇编语言中数组的长度如何计算、汇编 LENGTH,SIZE的问题、汇编基础知识六等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9774427.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存