原版全
计算机系统

零标志 ZF = 1 表示结果 F 为 0。不管对于无符号整数还是有符号整数运算,ZF 都有意义
符号标志 SF = 1 表示有符号数运算结果为负;有符号数运算结果为正时 SF = 0。对于无符号数运算,SF 没有意义。
无符号数都为正数
两数相加(sub=0)最高位有进位溢出(加了一个大的数,
两数相减(sub=1)最高位有借位溢出(被减的数越大,加上的补码越小,
综合来说
采用一位符号位
假设机器字长为 4(n = 4),能表示的有符号数范围为 -8 ~ 7,那么就有:
[5]补 = 0101,[4]补 = 0100;
[-5]补 = 1011,[-4]补 = 1100;
[5 + 4]补 = 0101 + 0100 = 1001 = [-7]补; (正溢出)
[5 - 4]补 = [5 + (-4)]补 = 0101 + 1100 = 1 0001 = [1]补;
[4 - 5]补 = [4 + (-5)]补 = 0100 + 1011 = 1111 = [-1]补;
[-5 - 4]补 = [-5 + (-4)]补 = 1011 + 1100 = 1 0111 = [7]补; (负溢出)
采用两位符号位
[5]补 = 00 101,[4]补 = 00 100;
[-5]补 = 11 011,[-4]补 = 11 100;
[5 + 4]补 = 00 101 + 00 100 = 01 001 = [1]补; (正溢出)
[5 - 4]补 = [5 + (-4)]补 = 00 101 + 11 100 = 1 00 001 = [1]补;
[4 - 5]补 = [4 + (-5)]补 = 00 100 + 11 011 = 11 111 = [-1]补;
[-5 - 4]补 = [-5 + (-4)]补 = 11 011 + 11 100 = 1 10 111 = [-1]补; (负溢出)





立即寻址

直接寻址

寄存器寻址

寄存器间接寻址

基址寻址

变址寻址

……
IA32汇编指令
前四个:a ->
add, b ->base, c ->count, d -> 'data'si: s ->
source-> 源地址, di ->destination-> 目的地址bp ->
base pointer, sp ->stack pointer
ATT & Intel

mov指令数据传递方向
ATT->
Intel<-

lea:load effective address,加载有效地址,将一个内存地址加载到目的寄存器;
push:将数据压入栈,同时 esp 减去数据长度;
pop:将栈顶数据弹出栈,同时 esp 加上数据长度;

除法指令,它们都只有一个操作数,表示除数,被除数则放在 edx : eax 中;得到的结果商放在 eax 中,余数放在 edx 中:
div:无符号除
idiv:有符号除

重置条件码
C程序
xxxxxxxxxx101int a = 23;2int b = 31;3if (a > b)4{5 a++;6}7else {8 a--;9}10printf(" a = %d\n", a);使用goto
xxxxxxxxxx81 if (a <= b)2 goto L1;3 a++;4 goto L2;5L1:6 a--;7L2:8 printf(" a = %d\n", a);汇编

使用vs2022 x86反汇编
xxxxxxxxxx211 int a = 23;200151896 mov dword ptr [ebp-8],17h 3 int b = 31;40015189D mov dword ptr [ebp-14h],1Fh 5 if (a > b)6001518A4 mov eax,dword ptr [ebp-8] 7001518A7 cmp eax,dword ptr [ebp-14h] 8001518AA jle 001518B7 9 {10 a++;11001518AC mov eax,dword ptr [ebp-8] 12001518AF add eax,1 13001518B2 mov dword ptr [ebp-8],eax 14 }15001518B5 jmp 001518C0 16 else {17 a--;18001518B7 mov eax,dword ptr [ebp-8] 19001518BA sub eax,1 20001518BD mov dword ptr [ebp-8],eax 21 }do - while循环C程序
xxxxxxxxxx51int a = 0;2do {3 a++;4} while (a < 5);5printf(" a = %d \n ", a);使用goto
x1 int a = 0;2L1:3 a++;4
5 if (a < 5)6 goto L1;7 printf(" a = %d \n ", a);汇编

xxxxxxxxxx101 int a = 0;2007A1896 mov dword ptr [ebp-8],0 3 do {4 a++;5007A189D mov eax,dword ptr [ebp-8] 6007A18A0 add eax,1 7007A18A3 mov dword ptr [ebp-8],eax 8 } while (a < 5);9007A18A6 cmp dword ptr [ebp-8],5 10007A18AA jl 007A189D while循环xxxxxxxxxx51int a = 0;2while (a < 5) {3 a++;4}5printf(" a = %d \n ", a);xxxxxxxxxx81 int a = 0;2L1:3 if (a >= 5)4 goto L2;5 a++;6 goto L1;7L2:8 printf(" a = %d \n ", a);
xxxxxxxxxx111 int a = 0;2007A18BD mov dword ptr [ebp-8],0 3 while (a < 5) {4007A18C4 cmp dword ptr [ebp-8],5 5007A18C8 jge 007A18D5 6 a++;7007A18CA mov eax,dword ptr [ebp-8] 8007A18CD add eax,1 9007A18D0 mov dword ptr [ebp-8],eax 10 }11007A18D3 jmp 007A18C4 for循环xxxxxxxxxx61int a = 10;2for (int i = 0; i < 5; i++)3{4 a--;5}6printf(" a = %d \n ", a);xxxxxxxxxx21for( 初始化循环变量; 判断循环条件; 更新循环变量)2 循环体xxxxxxxxxx71int a = 10;2int i = 0;3while (i < 5) {4 a--;5 i++;6}7printf(" a = %d \n ", a);xxxxxxxxxx101 int a = 10;2 int i = 0;3L1:4 if (i >= 5)5 goto L2;6 a--;7 i++;8 goto L1;9L2:10 printf(" a = %d \n ", a);
xxxxxxxxxx191 int a = 10;2007A18E6 mov dword ptr [ebp-8],0Ah 3 for (int i = 0; i < 5; i++)4007A18ED mov dword ptr [ebp-14h],0 5007A18F4 jmp 007A18FF 6007A18F6 mov eax,dword ptr [ebp-14h] 7007A18F9 add eax,1 8007A18FC mov dword ptr [ebp-14h],eax 9007A18FF cmp dword ptr [ebp-14h],5 10007A1903 jge 007A1910 11 {12 a--;13007A1905 mov eax,dword ptr [ebp-8] 14007A1908 sub eax,1 15007A190B mov dword ptr [ebp-8],eax 16 }17007A190E jmp 007A18F6 18 printf(" a = %d \n ", a);19007A1910 ...
流程
程序代码和数据:主要包括 只读代码段 和 读写段(.data 和 .bss)。对所有进程来说,代码都是从固定地址开始,紧接着就是 C 语言中的全局和静态数据。其中 .data 中是已初始化的全局和静态 C 变量,而 .bss 中是未初始化的全局和静态变量。
堆(Heap):用于运行时的动态内存分配,向上(高地址)生长。代码和数据区,在进程开始运行时就被指定了大小;而通过调用 malloc 和 free 这样的 C 标准库函数,可以让堆区动态地扩展和收缩。
共享库的内存映射区:用户区的中间部分是一块内存映射区域,用来存放像 C 标准库这样的共享库。(
printf)用户栈(Stack):位于虚拟地址空间用户区顶部,向下(低地址)生长。一般用来存储局部变量和函数参数,结合堆栈指针可以方便地实现函数的调用和返回。
从可执行文件加载

执行P指令
P函数局部变量入栈

调用Q函数
问题:
参数能够传递给Q函数
执行完Q函数能够返回到跳转语句的下一句
P函数中使用的寄存器的值应该被保存
依次由如下解决方案:
在P函数的栈帧中压入参数构造区和调用指令的下一条指令


eip寄存器传入跳转的指令的位置
在Q函数的栈帧中P寄存器的值入栈
xxxxxxxxxx151int add(int x, int y);2
3int main() {4 int a = 23;5 int b = 31;6
7 int sum = add(a, b);8
9 printf(" sum = %d\n", sum);10}11
12int add(int x, int y) {13 int sum = x + y;14 return sum;15}main栈帧
xxxxxxxxxx51# P的局部变量2 int a = 23;3005018F6 mov dword ptr [ebp-8],17h 4 int b = 31;5005018FD mov dword ptr [ebp-14h],1Fh EAX = 0050C008 EBX = 02636000 ECX = 0050C008 EDX = 00000001 ESI = 02636000
EDI =
028FF6BCEIP = 00501904 ESP = 028FF5CC EBP = 028FF6BC EFL = 00000246
xxxxxxxxxx61# 参数构造区2 int sum = add(a, b);300501904 mov eax,dword ptr [ebp-14h] # 参数b移到eax寄存器 400501907 push eax # eax压栈500501908 mov ecx,dword ptr [ebp-8] # 参数a移到ecx寄存器60050190B push ecx # ecx压栈EAX =
0000001FEBX = 02636000 ECX =00000017EDX = 00000001 ESI = 02636000EDI = 028FF6BC EIP = 0050190C ESP =
028FF5C4EBP = 028FF6BC EFL = 00000246
栈顶指针对应的内存地址

xxxxxxxxxx71# 调用Q函数(`add`)2# 跳转的同时,该地址的下一行地址作为返回地址入栈30050190C call 005010234
5---60050190C call 00501023 700501911 add esp,8 ESP = 028FF5C0

call位置
xxxxxxxxxx6100501023 jmp 005018702
3---4# 跳转到add函数起始位置5int add(int x, int y) {600501870 push ebp xxxxxxxxxx21# 将P的ebp栈基指针入栈200501870 push ebp ESP = 028FF5BC EBP = 028FF6BC

Q的栈帧开始
xxxxxxxxxx1100501871 mov ebp,esp # P的栈顶作为Q的栈基址初态: ESP = 028FF5BC EBP = 028FF6BC
末态: ESP = 028FF5BC EBP = 028FF5BC
xxxxxxxxxx1100501873 sub esp,0CCh # 加上一个较大的偏移量开辟栈空间ESP = 028FF4F0
xxxxxxxxxx41# 保存P的寄存器的值(ebx, esi, edi)入栈200501879 push ebx 30050187A push esi 40050187B push ediP寄存器值
EBX = 02636000 ESI = 02636000 EDI = 028FF6BC

此时:ESP = 028FF4E4
xxxxxxxxxx51# Q的局部变量 && Q局部变量执行Q语句2 int sum = x + y;300501896 mov eax,dword ptr [ebp+8] # Q的栈基址向上寻址,对应参数a放入eax 400501899 add eax,dword ptr [ebp+0Ch] # 参数a和eax的值作为alu的两个输入50050189C mov dword ptr [ebp-8],eax 


xxxxxxxxxx191# 调用Q结果返回2 return sum;30050189F mov eax,dword ptr [ebp-8] # 将结果移动到eax寄存器 4}5# 保存的P寄存器出栈6005018A2 pop edi 7005018A3 pop esi 8005018A4 pop ebx 9# 回收Q的栈空间地址10005018A5 add esp,0CCh 11# 维持P的栈顶esp12005018AB cmp ebp,esp 13005018AD call 00501253 14005018B2 mov esp,ebp15# 保存的P的栈基址出栈16005018B4 pop ebp 17# 返回地址出栈18005018B5 ret 19# 到此P的各寄存器值均恢复xxxxxxxxxx4100501911 add esp,8 200501914 mov dword ptr [ebp-20h],eax3printf(" sum = %d\n", sum);4...Cxxxxxxxxxx78123
4void merge(int arr[], int left, int mid, int right) {5 int n1 = mid - left + 1;6 int n2 = right - mid;7
8 int* leftArray = (int*)malloc(n1 * sizeof(int));9 int* rightArray = (int*)malloc(n2 * sizeof(int));10
11 for (int i = 0; i < n1; i++) {12 leftArray[i] = arr[left + i];13 }14 for (int j = 0; j < n2; j++) {15 rightArray[j] = arr[mid + 1 + j];16 }17
18 int i = 0, j = 0, k = left;19 while (i < n1 && j < n2) {20 if (leftArray[i] <= rightArray[j]) {21 arr[k] = leftArray[i];22 i++;23 }24 else {25 arr[k] = rightArray[j];26 j++;27 }28 k++;29 }30
31 while (i < n1) {32 arr[k] = leftArray[i];33 i++;34 k++;35 }36 while (j < n2) {37 arr[k] = rightArray[j];38 j++;39 k++;40 }41
42 free(leftArray);43 free(rightArray);44}45
46void mergeSort(int arr[], int left, int right) {47 if (left < right) {48 int mid = left + ((right - left) >> 1);49
50 mergeSort(arr, left, mid);51 mergeSort(arr, mid + 1, right);52
53 merge(arr, left, mid, right);54 }55}56
57void printArray(int arr[], int size) {58 for (int i = 0; i < size; i++) {59 printf("%d ", arr[i]);60 }61 printf("\n");62}63
64int main() {65 int arr[] = { 9, 5, 6, 2, 1, 4, 3, 7, 8, 10 };66 int arr_size = sizeof(arr) / sizeof(arr[0]);67
68 printf("排序前的数组: \n");69 printArray(arr, arr_size);70
71 mergeSort(arr, 0, arr_size - 1);72
73 printf("排序后的数组: \n");74 printArray(arr, arr_size);75
76 return 0;77}78
mainxxxxxxxxxx431int main() {200D418A0 push ebp 300D418A1 mov ebp,esp 400D418A3 sub esp,100h 500D418A9 push ebx 600D418AA push esi 700D418AB push edi 800D418AC lea edi,[ebp-40h] 900D418AF mov ecx,10h 1000D418B4 mov eax,0CCCCCCCCh 1100D418B9 rep stos dword ptr es:[edi] 1200D418BB mov eax,dword ptr ds:[00D4A000h] 1300D418C0 xor eax,ebp 1400D418C2 mov dword ptr [ebp-4],eax 1500D418C5 mov ecx,0D4C00Eh 1600D418CA call 00D41343 1700D418CF nop 18 int arr[] = { 9, 5, 6, 2, 1, 4, 3, 7, 8, 10 };1900D418D0 mov dword ptr [ebp-30h],9 2000D418D7 mov dword ptr [ebp-2Ch],5 2100D418DE mov dword ptr [ebp-28h],6 2200D418E5 mov dword ptr [ebp-24h],2 2300D418EC mov dword ptr [ebp-20h],1 2400D418F3 mov dword ptr [ebp-1Ch],4 2500D418FA mov dword ptr [ebp-18h],3 2600D41901 mov dword ptr [ebp-14h],7 2700D41908 mov dword ptr [ebp-10h],8 2800D4190F mov dword ptr [ebp-0Ch],0Ah 29 int arr_size = sizeof(arr) / sizeof(arr[0]);3000D41916 mov dword ptr [ebp-3Ch],0Ah 31
32 printf("排序前的数组: \n");3300D4191D push 0D47B38h 3400D41922 call 00D410D7 3500D41927 add esp,4 36 printArray(arr, arr_size);37# 参数构造区3800D4192A mov eax,dword ptr [ebp-3Ch] 3900D4192D push eax 4000D4192E lea ecx,[ebp-30h] # 加载数组的有效地址4100D41931 push ecx42# 调用printArray4300D41932 call 00D411EF ECX = 0x00AFF75C

printArrayxxxxxxxxxx331void printArray(int arr[], int size) {2# main的栈底入栈300D41D50 push ebp 4# main的栈顶作为printArray的栈底500D41D51 mov ebp,esp6# 开辟保存main寄存器值的空间700D41D53 sub esp,0CCh8# 归档main寄存器900D41D59 push ebx 1000D41D5A push esi 1100D41D5B push edi 12...13 for (int i = 0; i < size; i++) {1400D41D76 mov dword ptr [ebp-8],0 # i=01500D41D7D jmp 00D41D88 16# L1(i++)1700D41D7F mov eax,dword ptr [ebp-8]1800D41D82 add eax,1 1900D41D85 mov dword ptr [ebp-8],eax 20# L2(终止条件,>=跳转到程序外的地址)2100D41D88 mov eax,dword ptr [ebp-8] 2200D41D8B cmp eax,dword ptr [ebp+0Ch] 2300D41D8E jge 00D41DA9 24
25 printf("%d ", arr[i]);2600D41D90 mov eax,dword ptr [ebp-8] 2700D41D93 mov ecx,dword ptr [ebp+8] 2800D41D96 mov edx,dword ptr [ecx+eax*4] 2900D41D99 push edx 3000D41D9A push 0D47B30h 3100D41D9F call 00D410D7 3200D41DA4 add esp,8 33 }打印第一个数:
i传递给eax
mov eax,dword ptr [ebp-8]

arr的有效地址传递给ecx
mov ecx,dword ptr [ebp+8]


取出数组的第一个数赋给edx寄存器(使用比例变址寻址)
mov edx,dword ptr [ecx+eax*4]
xxxxxxxxxx1100D41DA7 jmp 00D41D7F # 跳转到L1mainxxxxxxxxxx111 mergeSort(arr, 0, arr_size - 1);2# arr_size-1300D4193A mov eax,dword ptr [ebp-3Ch] 400D4193D sub eax,1 500D41940 push eax 600D41941 push 07# arr有效地址800D41943 lea ecx,[ebp-30h] 900D41946 push ecx10
1100D41947 call 00D41280 mergeSortxxxxxxxxxx71void mergeSort(int arr[], int left, int right) {200D41C90 push ebp 300D41C91 mov ebp,esp 400D41C93 sub esp,0CCh 500D41C99 push ebx 600D41C9A push esi 700D41C9B push edixxxxxxxxxx51 if (left < right) {2# 终止条件300D41CB6 mov eax,dword ptr [ebp+0Ch] 400D41CB9 cmp eax,dword ptr [ebp+10h] 500D41CBC jge 00D41D0F 
xxxxxxxxxx91 int mid = left + ((right - left) >> 1);2# (right - left) >> 1300D41CBE mov eax,dword ptr [ebp+10h] 400D41CC1 sub eax,dword ptr [ebp+0Ch] 500D41CC4 sar eax,1 6# left + ()700D41CC6 add eax,dword ptr [ebp+0Ch] 8# 返回值从栈基址开始写入,此处只用了4个字节900D41CC9 mov dword ptr [ebp-8],eax xxxxxxxxxx201# 和main调用mergeSort一样递归调用2 mergeSort(arr, left, mid);300D41CCC mov eax,dword ptr [ebp-8] 400D41CCF push eax 500D41CD0 mov ecx,dword ptr [ebp+0Ch] 600D41CD3 push ecx 700D41CD4 mov edx,dword ptr [ebp+8] 800D41CD7 push edx 900D41CD8 call 00D41280 1000D41CDD add esp,0Ch 11 mergeSort(arr, mid + 1, right);1200D41CE0 mov eax,dword ptr [ebp+10h] 1300D41CE3 push eax 1400D41CE4 mov ecx,dword ptr [ebp-8] 1500D41CE7 add ecx,1 1600D41CEA push ecx 1700D41CEB mov edx,dword ptr [ebp+8] 1800D41CEE push edx 1900D41CEF call 00D41280 2000D41CF4 add esp,0Ch mergexxxxxxxxxx71void merge(int arr[], int left, int mid, int right) {200D41A00 push ebp 300D41A01 mov ebp,esp 400D41A03 sub esp,12Ch 500D41A09 push ebx 600D41A0A push esi 700D41A0B push edixxxxxxxxxx111 int n1 = mid - left + 1;2# 计算左侧数组的长度放到[ebp-8]的位置300D41A26 mov eax,dword ptr [ebp+10h] 400D41A29 sub eax,dword ptr [ebp+0Ch] 500D41A2C add eax,1 600D41A2F mov dword ptr [ebp-8],eax 7 int n2 = right - mid;8# 计算右侧数组的长度放到[ebp-20]的位置900D41A32 mov eax,dword ptr [ebp+14h] 1000D41A35 sub eax,dword ptr [ebp+10h] 1100D41A38 mov dword ptr [ebp-14h],eax xxxxxxxxxx771 // 创建临时数组2 int* leftArray = (int*)malloc(n1 * sizeof(int));3# 数组的字节数 长度*4400D41A3B mov eax,dword ptr [ebp-8] 500D41A3E mov ecx,4 600D41A43 mul eax,ecx7## 了解:防止乘法溢出800D41A45 mov edx,0FFFFFFFFh 900D41A4A cmovb eax,edx # 条件传送指令之一,该指令成立条件(~CF)10# 保存当前栈顶指针1100D41A4D mov esi,esp 12# 调用malloc1300D41A4F push eax 1400D41A50 call dword ptr ds:[00D4B170h] 1500D41A56 add esp,4 1600D41A59 cmp esi,esp 1700D41A5B call 00D41262 1800D41A60 mov dword ptr [ebp-20h],eax 19
20 int* rightArray = (int*)malloc(n2 * sizeof(int));2100D41A63 mov eax,dword ptr [ebp-14h] 2200D41A66 mov ecx,4 2300D41A6B mul eax,ecx 2400D41A6D mov edx,0FFFFFFFFh 2500D41A72 cmovb eax,edx 2600D41A75 mov esi,esp 2700D41A77 push eax 2800D41A78 call dword ptr ds:[00D4B170h] 2900D41A7E add esp,4 3000D41A81 cmp esi,esp 3100D41A83 call 00D41262 3200D41A88 mov dword ptr [ebp-2Ch],eax 33
34 for (int i = 0; i < n1; i++) {3500D41A8B mov dword ptr [ebp-38h],0 3600D41A92 jmp 00D41A9D 37# L1 (i++)3800D41A94 mov eax,dword ptr [ebp-38h] 3900D41A97 add eax,1 4000D41A9A mov dword ptr [ebp-38h],eax 41# L2 (>=n1跳出)4200D41A9D mov eax,dword ptr [ebp-38h] 4300D41AA0 cmp eax,dword ptr [ebp-8] 4400D41AA3 jge 00D41ABC 45 leftArray[i] = arr[left + i];4600D41AA5 mov eax,dword ptr [ebp+0Ch] # left 4700D41AA8 add eax,dword ptr [ebp-38h] # left+i4800D41AAB mov ecx,dword ptr [ebp-38h] 4900D41AAE mov edx,dword ptr [ebp-20h] # leftArray有效地址 5000D41AB1 mov esi,dword ptr [ebp+8] # arr有效地址51# 比例变址寻址,比例因子4为字节,eax,ecx寄存器中保存的是对应index5200D41AB4 mov eax,dword ptr [esi+eax*4] # eax <-arr[left + 1] 5300D41AB7 mov dword ptr [edx+ecx*4],eax # leftArray[i] <- eax 54 }5500D41ABA jmp 00D41A94 # 跳转L156
57# 同上58 for (int j = 0; j < n2; j++) {5900D41ABC mov dword ptr [ebp-44h],0 6000D41AC3 jmp 00D41ACE 6100D41AC5 mov eax,dword ptr [ebp-44h] 6200D41AC8 add eax,1 6300D41ACB mov dword ptr [ebp-44h],eax 6400D41ACE mov eax,dword ptr [ebp-44h] 6500D41AD1 cmp eax,dword ptr [ebp-14h] 6600D41AD4 jge 00D41AF1 67 rightArray[j] = arr[mid + 1 + j];6800D41AD6 mov eax,dword ptr [ebp-44h] 6900D41AD9 mov ecx,dword ptr [ebp+10h] 7000D41ADC lea edx,[ecx+eax+1] 7100D41AE0 mov eax,dword ptr [ebp-44h] 7200D41AE3 mov ecx,dword ptr [ebp-2Ch] 7300D41AE6 mov esi,dword ptr [ebp+8] 7400D41AE9 mov edx,dword ptr [esi+edx*4] 7500D41AEC mov dword ptr [ecx+eax*4],edx 76 }7700D41AEF jmp 00D41AC5xxxxxxxxxx1071/*合并数组2 回忆归并排序:(由于递归调用,所以每次合并左右数组均认为有序)3 1. 左右数组均还有元素,一次比较对应指针索引的值,取小填入,填入的数组对应的索引+14 2. 一侧数组无元素,直接在尾部合并 */5# 情景一6 int i = 0, j = 0, k = left;700D41AF1 mov dword ptr [ebp-50h],0 800D41AF8 mov dword ptr [ebp-5Ch],0 900D41AFF mov eax,dword ptr [ebp+0Ch] # left1000D41B02 mov dword ptr [ebp-68h],eax 11 while (i < n1 && j < n2) {12# i >= n1跳出1300D41B05 mov eax,dword ptr [ebp-50h]1400D41B08 cmp eax,dword ptr [ebp-8] 1500D41B0B jge 00D41B6C16# i >= n2跳出1700D41B0D mov eax,dword ptr [ebp-5Ch] 1800D41B10 cmp eax,dword ptr [ebp-14h] 1900D41B13 jge 00D41B6C 20
21# branch22 if (leftArray[i] <= rightArray[j]) {2300D41B15 mov eax,dword ptr [ebp-50h] # i 2400D41B18 mov ecx,dword ptr [ebp-20h] # leftArray的有效地址2500D41B1B mov edx,dword ptr [ebp-5Ch] # j2600D41B1E mov esi,dword ptr [ebp-2Ch] # rightArray的有效地址2700D41B21 mov eax,dword ptr [ecx+eax*4] 2800D41B24 cmp eax,dword ptr [esi+edx*4] 2900D41B27 jg 00D41B46 # >跳出30 arr[k] = leftArray[i];3100D41B29 mov eax,dword ptr [ebp-68h] # left/k 3200D41B2C mov ecx,dword ptr [ebp+8] # arr的有效地址3300D41B2F mov edx,dword ptr [ebp-50h] # i3400D41B32 mov esi,dword ptr [ebp-20h] # leftArray的有效地址3500D41B35 mov edx,dword ptr [esi+edx*4] 3600D41B38 mov dword ptr [ecx+eax*4],edx 37 i++;3800D41B3B mov eax,dword ptr [ebp-50h] 3900D41B3E add eax,1 4000D41B41 mov dword ptr [ebp-50h],eax 41 }4200D41B44 jmp 00D41B61 # 跳转到k++43 else {44 arr[k] = rightArray[j];4500D41B46 mov eax,dword ptr [ebp-68h] 4600D41B49 mov ecx,dword ptr [ebp+8] 4700D41B4C mov edx,dword ptr [ebp-5Ch] 4800D41B4F mov esi,dword ptr [ebp-2Ch] 4900D41B52 mov edx,dword ptr [esi+edx*4] 5000D41B55 mov dword ptr [ecx+eax*4],edx 51 j++;5200D41B58 mov eax,dword ptr [ebp-5Ch] 5300D41B5B add eax,1 5400D41B5E mov dword ptr [ebp-5Ch],eax 55 }56 57 # 修改arr的指针右移 58 k++;5900D41B61 mov eax,dword ptr [ebp-68h] 6000D41B64 add eax,1 6100D41B67 mov dword ptr [ebp-68h],eax 62 }6300D41B6A jmp 00D41B05 # 跳转while循环64
65# 情景二:复制剩余元素(基本同上)66 while (i < n1) {6700D41B6C mov eax,dword ptr [ebp-50h] 6800D41B6F cmp eax,dword ptr [ebp-8] 6900D41B72 jge 00D41B9A 70 arr[k] = leftArray[i];7100D41B74 mov eax,dword ptr [ebp-68h] 7200D41B77 mov ecx,dword ptr [ebp+8] 7300D41B7A mov edx,dword ptr [ebp-50h] 7400D41B7D mov esi,dword ptr [ebp-20h] 7500D41B80 mov edx,dword ptr [esi+edx*4] 7600D41B83 mov dword ptr [ecx+eax*4],edx 77 i++;7800D41B86 mov eax,dword ptr [ebp-50h] 7900D41B89 add eax,1 8000D41B8C mov dword ptr [ebp-50h],eax 81 k++;8200D41B8F mov eax,dword ptr [ebp-68h] 8300D41B92 add eax,1 8400D41B95 mov dword ptr [ebp-68h],eax 85 }8600D41B98 jmp 00D41B6C 87 while (j < n2) {8800D41B9A mov eax,dword ptr [ebp-5Ch] 8900D41B9D cmp eax,dword ptr [ebp-14h] 9000D41BA0 jge 00D41BC8 91 arr[k] = rightArray[j];9200D41BA2 mov eax,dword ptr [ebp-68h] 9300D41BA5 mov ecx,dword ptr [ebp+8] 9400D41BA8 mov edx,dword ptr [ebp-5Ch] 9500D41BAB mov esi,dword ptr [ebp-2Ch] 9600D41BAE mov edx,dword ptr [esi+edx*4] 9700D41BB1 mov dword ptr [ecx+eax*4],edx 98 j++;9900D41BB4 mov eax,dword ptr [ebp-5Ch] 10000D41BB7 add eax,1 10100D41BBA mov dword ptr [ebp-5Ch],eax 102 k++;10300D41BBD mov eax,dword ptr [ebp-68h] 10400D41BC0 add eax,1 10500D41BC3 mov dword ptr [ebp-68h],eax 106 }10700D41BC6 jmp 00D41B9A xxxxxxxxxx201# 释放临时数组空间(free函数调用,和其他函数调用的流程一样)2 free(leftArray);300D41BC8 mov esi,esp 400D41BCA mov eax,dword ptr [ebp-20h] 500D41BCD push eax 600D41BCE call dword ptr ds:[00D4B174h] 700D41BD4 add esp,4 800D41BD7 cmp esi,esp 900D41BD9 call 00D41262 1000D41BDE nop 11 free(rightArray);1200D41BDF mov esi,esp 1300D41BE1 mov eax,dword ptr [ebp-2Ch] 1400D41BE4 push eax 1500D41BE5 call dword ptr ds:[00D4B174h] 1600D41BEB add esp,4 1700D41BEE cmp esi,esp 1800D41BF0 call 00D41262 1900D41BF5 nop 20}1# 执行完函数后出栈返回200D41BF6 pop edi 300D41BF7 pop esi 400D41BF8 pop ebx 500D41BF9 add esp,12Ch 600D41BFF cmp ebp,esp 700D41C01 call 00D41262 800D41C06 mov esp,ebp 900D41C08 pop ebp 1000D41C09 ret