题目如下图
主要是汇编的寄存器分不清各种的作用是什么。
不同位的寄存器名称:64位 -r 32位 -e
栈帧:C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。
栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。
注意:EBP指向当前位于系统栈最上边一个栈帧的底部,而不是系统栈的底部。严格说来,“栈帧底部”和“栈底”是不同的概念;ESP所指的栈帧顶部和系统栈的顶部是同一个位置。
ax(accumulator):用于存放函数的返回值
bp(base pointer): 用于存放执行中的函数对应的栈帧的栈底地址
sp(stack poinger): 用于存放执行中的函数对应的栈帧的栈顶地址
ip(instruction pointer): 指向当前执行指令的下一条指令
32位中各寄存器作用:
一步一步来:
push rbp //入栈,将rbp寄存器的值压入调用bp栈中
mov rbp,rsp //建立新的栈帧,将被调函数的栈帧栈底地址rsp放入rbp
mov QWORD PTR[rbp-0x18],rdi //(QWORD 四字 Q(quad-)) 在rdi到 [rpb-0x18]处存传进来的第一个参数
mov DWORD PTR[rbp-0x1c],esi //在esi到 [rbp-0x1c]处存传进来的第二个参数
mov DWORD PTR [rbp-0x4],0x1 // 在内存[rbp-0x4]除写入1
jmp 400522 <func+0x3c> //跳转到400522处
400522: mov eax,DOWRD PTR[rbp-0x4] //读取[rbp-0x4] 所以eax=1
cmp eax,DWORD PTR [rbp-0x1c] //比较eax与内存[rbp-0x1c]的值 将[rbp-0x1c] 处的值(参数2)和eax的值(参数1)作差; //cmp A,B 若A小于等于B 则执行jle指令 进行跳转 否则不进行
jle 4004fa<func+0x14>
nop //一个字节的空指令
pop rbp //函数调用结束 弹出栈底指针
4004fa:mov eax,DWORD PTR [rbp-0x4] //eax=1
movsxd rdx,eax //rdx=1 movsxd指令:带符号扩展传送指令,符号扩展的意思是,当计算机存储某一个有符号数时,符号位位于该数的第一位,所以,当扩展一个负数的时候需要将扩展的高位全赋为1.对于正数而言,符号扩展和零扩展MOVZX是一样的,将扩展的高位全赋为0.
mov rax,QWORD PTR [rbp-0x18] //rax=input[0] 即第一个参数
add rax,rdx //rax+=rdx
mov edx,DWORD PTR [rbp-0x4] //[rbp-0x4]的值1给edx
movsxd rcx,edx//将edx的值带符号扩展,并传送至rcx中 rcx=1
mov rdx,QWORD PTR [rbp-0x18]
add rdx,rcx
movzx ecx,BYTE PTR [rdx]
mov edx,DWORD PTR [rbp-0x4]
xor edx,ecx//edx与ecx异或 //i^input[0]
mov BYTE PTR [rax],dl
add DWORD PTR [rbp-0x4],0x1//[rbp-0x4]++
QAQ
最后把上面的汇编翻译成C语言就是:
void func(char input[],int num)
{
int i =1;
while( i < num)
{ *(input[0]+i) ^= i; i++ }
}
然后用Python 或 c++ 实现以下就行
网友评论