Asm中的数组研究
前言:
这个不算是asm魅力系列的文章,只是回答一个朋友的问题!因为写的长了就发出来,希望对大家有帮助!
问题:
http://bbs.pediy.com/showthread.php?p=694325#poststop
任何语言中的数组实际上都是指针的概念,你这样想,一些数据放在内存的一个区域里面,我们要怎么访问他们呢?
步骤:
首先我们得知道这些数据在哪个内存块。其次要知道怎么在这个内存块里面找到我们要的那个指定的数据!
C或者是其他的高级语言把这些东西格式化了,比如char a[]={1,2,3,4};然后访问的时候 a[0] a[1] a[2] a[3] 实际上还是以前的老话,你要是理解了这种抽象过的符号表示的话,其实是很好理解的。但是asm比较接近人的思维,什么思维呢?就是我在步骤里提到的这种人人都能立刻想到的思路!
(一)
我先就用masm来说把!那么masm也做了一些格式化,所以我们操作数组也可以比较方便!
来看一小段:
代码:
.data Array BYTE 1,2,3 .code Mov esi,OFFSET Array
是和C一样简单的。
关键就是offset,他是干什么呢?就是相当于是把当前的指针指向Array这个内存区域的起始。OK。
那么来看这样的两个定义
来看两段定义:
代码:
arrayA BYTE 1h,2h,3h,4h arrayB WORD 1000h,2000h,3000h,4000h
我举个例子:
代码:
.data arrayB WORD 1000h,2000h,3000h,4000h .code Mov esi,offset arrayB Mov eax,[esi] Add esi,4
(二)
上面看到了,实际上inc esi这样是很麻烦的。那么好呢容易想到变址操作数。
那么
变址操作数的话,我们可以这样写:
代码:
.data arrayB WORD 1000h,2000h,3000h,4000h .code Mov esi,offset arrayB Mov eax,[esi] Mov ebx,[esi+2] Mov ecx,[esi+4]
那么我们这样访问元素:
代码:
.data arrayB WORD 1000h,2000h,3000h,4000h .code Mov esi,0h Mov eax,[arrayB+esi] Mov ebx,[arrayB+esi+2] Mov ecx,[arrayB+esi+4]
(三)
我们先看个c语言的小例子:
代码:
#include "stdio.h" #include "stdlib.h" int main() { char a[2]={1,2}; for(int i=0;i<sizeof(a);i++) { printf("%d\n",a[i]); } return 0; }
那么我们也可以这样:
代码:
#include "stdio.h" #include "stdlib.h" int main() { char a[2]={1,2}; for(int i=0;i<sizeof(a);i++) { printf("%d\n",*a+i); } return 0; }
那么用指针的概念,来操作数组的话,asm里面同样可以写:
代码:
.data Array db 1h,2h,3h,4h .code Point PTR BYTE Array Mov esi,point Mov eax,[esi]
对于c里面的a[i]这样的东西你反汇编看下,实际上用的就是变址:
代码:
9: printf("%d\n",a[i]); 0040D738 mov ecx,dword ptr [ebp-8] 0040D73B movsx edx,byte ptr [ebp+ecx-4]
建议你遇到这样的问题要多思考,不要只想着问,因为这些都是基本的程序层面的问题!
用我师傅achillis的话说:这叫编码!
我很赞同这个说法,这些层面的东西都只能叫做编码,只是在遵循一些规则。大牛是什么?
大牛就是充分的了解了这些规则,熟练的变通这些规则,甚至突破规则!