section .data ; 数据段声明 same db "same",0ah ; 0ah 是换行 diff db "diff",0ah ; 0ah 是换行 data dd 3 ; dd告诉汇编器占4个字节,db告诉汇编器占一个字节 section .stack stack db 1,3,2,4 ;申请4字节的栈空间 section .text ; 代码段声明 global _start ; 指定入口函数 _start: ; 在屏幕上显示一个字符串 mov eax,3 ; 立即数 mov ecx,eax ; 寄存器寻址 cmp ecx,3 ; 判断ecx 是否等于3 call print mov ecx,data ;data的地址 cmp ecx,3 ;判断ecx 是否等于3 call print mov ecx,[ecx+0] ;直接寻址(ecx中的地址作为地址+偏移)上的值 cmp ecx,3 ;判断ecx 是否等于3 call print mov ecx,[data+0] ;直接寻址(data的起始地址+偏移)上的值 cmp ecx,3 ;判断ecx 是否等于3 call print call exit print: ; 输出字符 JE NEXT ;比较上次对比指令的结果,相同则跳转到next push 5 ;传输第二个参数,字符串长度 push diff ;传输第一个参数,字符串地址 call loopShow add esp,8 ;回收2个参数 ret ;退出函数,否则回继续执行next NEXT: push 5 ;传输第二个参数,字符串长度 push same ;传输第一个参数,字符串地址 call loopShow add esp,8 ;回收2个参数 ret loopShow: push ebp ; 保存上一个函数的ebp mov ebp,esp ; 得到当前函数的ebp push ecx ;当前函数中需要用到ecx,需要先保存现场 push edx ;当前函数中需要用到edx,需要先保存现场 mov edx, [ebp+12] ;读取第二个参数 push edx ;第二个参数入栈,传到下个函数 mov edx, [ebp+8] ;读取第一个参数 push edx ;第一个参数入栈,传到下个函数 mov ecx,3 ;循环输出3次 s: call show ;调用函数输出字符串 loop s ;先ecx-=1,如果ecx=0,则退出循环 add esp,8 ;回收2个参数的空间 pop edx ;恢复现场 pop ecx ;恢复现场 pop ebp ; 恢复上个函数的ebp ret show: push ebp ; 保存上一个函数的ebp mov ebp,esp ; 得到当前函数的ebp push eax ; 保存当前函数要用寄存器,保证不会覆盖原值 push ecx ; 保存当前函数要用寄存器,保证不会覆盖原值 push edx ; 保存当前函数要用寄存器,保证不会覆盖原值 mov edx, [ebp+12] ; 参数三:字符串长度 mov ecx, [ebp+8] ; 参数二:要显示的字符串 mov ebx, 1 ; 参数一:文件描述符(stdout) mov eax, 4 ; 系统调用号(sys_write) int 0x80 ; 调用内核功能 pop edx ;恢复现场 pop ecx ;恢复现场 pop eax ;恢复现场 pop ebx ;恢复现场 ret exit: mov ebx, 0 ; 参数一:退出代码 mov eax, 1 ; 系统调用号(sys_exit) int 0x80 ; 调用内核功能