汇编学习(3)

字符串处理指令:
lods: 从[esi]传给累加器,根据df和操作字长调整esi
stos: 从累加器传给[edi],根据df和操作字长调整edi
movs: 直接从[esi]传到[edi],,根据df和操作字长调整esi和edi
scas: 累加器与[edi]相减比较,不影响操作数,影响标志位
cmps: [esi]与[edi]相减比较,不影响操作数,影响标志位

重复前缀:
rep: 若ecx=0,结束重复,否则ecx减1,重复操作
repz/repe: 若ecx=0或zf=0,结束重复,否则ecx减1,重复操作
repnz/repne: 若ecx=0或zf=1,结束重复,否则ecx减1,重复操作

1.字符串拼接

 char s1[81], s2[81], s3[81];
 printf("s1 = ");
 scanf("%s", s1);
 printf("s2 = ");
 scanf("%s", s2);
 _asm{
	  lea  edi, s3
	  lea  esi, s1  //獲取s1存儲地址
	L1:
	  movsb
	  cmp  [esi-1], 0
	  jne  L1
	  dec  edi   //刪除s1的終止符
	  lea  esi, s2  //獲取s2存儲地址
	L2:
	  movsb
	  cmp  [esi-1], 0
	  jne  L2
 }
 printf("s1 + s2 = %s\n", s3);

2.消除字符串标点

 char s1[81], s2[81];
 printf("s = ");
 scanf("%s", s1);
 _asm{
	  lea  esi, s1
	  lea  edi, s2
	  lea  edx, judge
	R:
	  lodsb
	  test al, al
	  je  END
	  push ebp
	  push eax
	  mov  ebp, esp
	  call edx
	  test eax, eax
	  pop  eax
	  pop  ebp
	  je  L  //若判定為標點,則不傳送該字符
	  stosb
	L:
	  jmp  R
	END:
	  mov  al, 0 //添加終止符
	  stosb
 }
 printf("消除標點后s = %s\n", s2);
 return;
 _asm{
	judge:
	  push ebx
	  mov  eax, 1
	  mov  bl, [ebp]
	  cmp  bl, 32
	  jl  f
	  cmp  bl, 47
	  jle  is_p
	  cmp  bl, 58
	  jl  f
	  cmp  bl, 64
	  jle  is_p
	  cmp  bl, 91
	  jl  f
	  cmp  bl, 96
	  jle  is_p
	  cmp  bl, 123
	  jl  f
	  cmp  bl, 126
	  jle  is_p
	  jmp  f
	is_p:
	  mov  eax, 0
	f:
	  pop  ebx
	  ret
 }

note:
32-47 标点1区(32是空格)
58-64 标点2区
91-96 标点3区
123-126 标点4区
48-57 数字
65-90 大写字母
97-122 小写字母
0-31 是打印控制
127是删除

3.求s1中首个出现在s2中的字符的位置

 int result;
 char s1[81], s2[81];
 printf("s1 = ");
 scanf("%s", s1);
 printf("s2 = ");
 scanf("%s", s2);
 _asm{
	  //統計s2長度
	  lea  esi, s2
	  mov  edx, -1
	R:
	  inc  edx
	  lodsb
	  test al, al
	  jne  R
	  //初始化
	  lea  esi, s1
	  mov  ebx, -1
	L:
	  lodsb   //裝入下一個s1字符
	  inc  ebx  //位置加一
	  test al, al
	  je  END1
	  mov  ecx, edx//初始化ecx為s2長度
	  lea  edi, s2
	  repne scasb
	  je  END2 //如果ZF=0,説明找到相同字符
	  jmp  L
	END1:
	  mov  ebx, -1 //設置位置為-1
	END2:
	  mov  result, ebx
 }
 printf("s1中首個出現在s2的字符位置為 %d\n", result);

4.求s1首次出现s2的位置

 int result;
 char s1[81], s2[81];
 printf("s1 = ");
 scanf("%s", s1);
 printf("s2 = ");
 scanf("%s", s2);
 _asm{
	  //統計s2長度
	  lea  esi, s2
	  mov  edx, -1
	R:
	  inc  edx
	  lodsb
	  test al, al
	  jne  R
	  //初始化
	  lea  esi, s1
	  mov  ebx, -1
	  dec  esi
	L:
	  inc  esi
	  inc  ebx  //位置加一
	  mov  al, [esi]
	  test al, al
	  je  END1
	  mov  ecx, edx//初始化ecx為s2長度
	  push esi  //保存s1開始匹配位置
	  lea  edi, s2
	  repe cmpsb  //匹配s1子串和s2
	  pop  esi  //恢復s1開始匹配位置
	  jne  L
	  cmp  ecx, 0
	  je  END2 //如果ecx=0,説明匹配到和s2相同的子串
	END1:
	  mov  ebx, -1 //設置位置為-1
	END2:
	  mov  result, ebx
 }
 printf("s1中首次出現s2位置為 %d\n", result);

5.生成由n个字符c形成的字符串

 char c;
 int n;
 char s[81];
 printf("ch = ");
 scanf("%c", &c);
 printf("n = ");
 scanf("%d", &n);
 _asm{
	  mov  al, c
	  mov  ecx, n
	  lea  edi, s
	  lea  edx, cstring
	  //參數壓棧
	  push ebp
	  push eax
	  push ecx
	  push edi
	  mov  ebp, esp
	  call edx  //調用函數生成字符串
	  pop  ebp  //恢復棧幀
 }
 printf("生成的字符串為:  %s\n",  s);
 return;
 _asm{
	cstring:
	  mov  edi, [ebp]  //獲取參數s
	  mov  ecx, [ebp+4] //獲取參數n
	  mov  al, [ebp+8]  //獲取參數c
	  rep stosb   //存儲n此字符c
	  mov  al, 0
	  stosb    //存儲終止符
	  ret  12
 }

内联汇编关键字与外部定义的变量重名时,会优先认定为前者

猜你喜欢

转载自blog.csdn.net/qq_21110935/article/details/82904517