C语句与汇编
学习了汇编语言之后,就需要将常用的C语言代码结构与相应的汇编语言联系起来。这样就可以在分析汇编语言的时候,明白它的意思。C语言中函数过程的调用,循环语句,条件语句,结构体与数组的访问都有对应的特定的汇编语言结构。下面来分别分析这些特定的结构。
有些在C层面不好理解的代码,只要分析下它的汇编,就很容易明白其中的原理了,比如之前学习的函数的调用约定,函数的传参等。
4.1.1 循环语句(for,while,do-while)与汇编
For循环语句的汇编代码:
C代码:
for(int i=0;i<10;i++)
{
…
}
汇编代码:
i=0;
jmp A;
B:
i++
A:
cmp i, 0ah
jge OUT;
.....
jmp B;
OUT:
While循环语句的汇编代码:
while(i<10)
{
i++;
}
A:
cmp i,0ah
jge OUT;
......
i++;
jmp A;
OUT:
4.1.2 if语句与汇编
if-else语句汇编代码:
if(i>0)
{
…
}
else
{
…
}
汇编代码:
cmp i,0
jle ELSE;
....
jmp OUT;
ELSE:
....
OUT:
Switch语句的汇编代码:
switch(value)
{
case 1:
…
break;
case 2:
…
break;
default:
}
switch:
cmp value, 1
je A;
cmp value, 2
je B;
jmp DEFAULT;
A:
...
jmp OUT
B:
...
jmp OUT
DEFAULT:
...
OUT:
4.1.3 数组访问与汇编
数组访问的汇编代码如下:
int g_a[100]={100,99,98,97,0};
for(int i = 0; i<100;i++)
0093149E mov dword
ptr [i],0
009314AA add eax,1
009314AD mov dword ptr [i],eax
009314B0 cmp dword ptr [i],64h
009314B4 jge wmain+46h
(
{
g_a[i]=10;
009314B6 mov eax,dword ptr [i]
009314B9 mov dword ptr g_a (937000h)[eax*4],0Ah //数组首地址+i*4
}
4.1.4 结构体访问与汇编
结构体中成员访问汇编代码如下:
typedef struct _S
{
int val;
char ch;
}S,*PS;
S g_s1;
g_s1.val=100;
0030149E mov dword
ptr [g_s1 (307344h)],64h //结构体首地址+偏移量(0)
g_s1.ch='A';
4.1.5 结构体数组与汇编
结构体数组成员访问汇编代码如下:
typedef struct _S
{
int val;
char ch;
}S,*PS;
S g_as[100]={{0}};
for(int i = 0;i<100;i++)
00FA149E mov dword
ptr [i],0
00FA
00FA
00FA14AA add eax,1
00FA14AD mov
dword ptr [i],eax
00FA14B0 cmp dword
ptr [i],64h
00FA14B4 jge wmain+51h
(0FA14D1h)
{
g_as[i].val=100;
00FA14B6 mov eax,dword
ptr [i]
00FA14B9 mov dword
ptr g_as (0FA7328h)[eax*8],64h //数组首地址+i*8+偏移(0)
g_as[i].ch='Z';
00FA
00FA
}
4.1.6 i++与汇编
int i = 0;
00FC14D4 mov dword ptr [i],0
i++;
00FC14DB mov eax,dword ptr [i]
00FC14DE add eax,1
00FC14E1 mov dword ptr [i],eax
可见,对于在C语言中的一条语句,在汇编层也有可能是多条汇编指令组成。因此,即使在单核多线程环境下,i++也不是多线程安全的,因为它不是原子操作,因为一个线程执行了i++某一条汇编指令,CPU的时间片就有可能用完了,发生了切换,而另外一个线程切换进来之后,又开始从头开始执行i++的汇编指令,因此造成多线程不一致性。
因此,要保证i++语句的多线程安全,要么使用锁机制,要么使用原子操作:比如Windows平台的InterLockedIncrement()函数或者Linux平台的atomic_t类型以及相关的操作。