怎样将汇编语言转换为C语言

怎样将汇编语言转换为C语言,第1张

如果是VC则在编译器命令行参数再加 /FA 则会生成汇编代码。如果参数是 /FAs 则会同时将源码和汇编代码。

/FA 程序集代码;.asm

/FAc 机器码和程序集代码;.cod

/FAs 源代码和程序集代码;.asm

/FAcs 机器码、源代码和程序集码;.cod

/Fa的用法

/Fa 为编译中的每个源代码文件创建一个源文件.asm。

/Fa文件名 将文件名.asm 放到当前目录中。仅在编译单个源代码文件时有效。

/Fa文件名.扩展名 将文件名.扩展名放到当前目录中。仅在编译单个源代码文件时有效。

/Fa目录\ 为编译中的每个源代码文件创建一个源文件.asm,并将其放到指定目录中。请注意必须有后缀反斜杠。只允许使用当前磁盘上的路径。

/Fa目录\文件名 将文件名.asm 放到指定目录中。仅在编译单个源代码文件时有效。

/Fa目录\文件名.扩展名 将文件名.扩展名放到指定目录中。仅在编译单个源代码文件时有效。

如果你是用gcc 或 g++编译器,如dev c++则加入命令行参数 -S 即可

将汇编语言转换成c语言,只能是手工写c语言了。

如果是反过来,C语言程序编译后可以生成汇编程序。但汇编程序却不能生成C语言程序。

别发图片,发源程序,也许会有人复制下来,帮你写。可这图片没法看,更不能复制,那就没人愿意做了。

如何将这段汇编语言转换成C语言?题目分别提供了同一C语言代码的32位和64位汇编版本:很容易可以得出其源C语言代码:

int f(int** p){

return (**p=**p+4,*(int*)**p)

}

函数体的返回值类型是int,参数p的类型是int**,其唯一的语句是return (**p=**p+4,*(int*)**p)

先把结论放在这,节约不想思考的同学的时间,不同编译器可能会有所不同,lea 0x4(%eax),%ecx指令可能会被编译器拆开成两段:mov (%eax),%ecx 和add 0x4,%ecx(对于64位,则是编译器把lea lea 0x4(%rax),%rcx,拆开成mov (%rax),%rcx 和add 0x4,%rcx,但是效果是一样的。

根据题目中函数体只有1句代码的信息,我们至少确定了这个代码是一个return语句,如此短小的函数当然只需要用到段内跳转和段内指针,不需要段地址信息,所以指针大小(64位的RIP和32位的EIP)只是偏移量大小,分别为64位(8字节)和32位(4字节)。

题目的设问有相当好的引导性,对比查看左边和右边的倒数第3个指令,我们可以看出:函数的返回值都是放在eax变量之中,说明返回值的类型大小是4个字节。而同时,我们知道在C语言中,64位和32位环境下,int类型的大小都是4个字节,所以第1空的答案不能是只有1字节的char类型,也不能是在32位环境下大小为4字节而在64位环境下大小为8字节的指针类型如char*、int*。综上,第1空的答案:函数f的返回值类型只能是int。

第2空则是考查C语言函数的参数传递,栈式参数传递,在call函数f把ip压入(分别为64位的RIP和32位的EIP)之前,先压入的是函数的实际参数,其类型暂时不知道,那就得从汇编指令中找出这个信息点:

C语言函数体标志就是:push %ebp→mov %esp,%ebp→函数体内部→pop %ebp→ret(对64位则是:push %rbp→mov %rsp,%rbp→函数体内部→pop %rbp→retq)

两边都是同一个简单的c语句得到的汇编语句(64位和32位),左边64位的第2、3、4行对应于右边的第2、3行(64位多用了一个rdi寄存器传递参数,可能是编译器选项不同的缘故,又因为main函数中调用函数f的指令没有给出,且不一定相同,故不影响判断)。

两边剩下的几行代码(左边2、3、4、5、6、7、8行,右边2、3、4、5、6、7行)的工作大同小异,从数据流上看(函数体内,对于32位0x8(%ebp)是第一个也是唯一一个参数,对于64位-0x8(%rbp)才是):

*p→eax,*eax→eax,eax+4→ecx(①),*p→edx,ecx→*edx,*eax→eax

可以简化为:

**p→eax,eax+4→ecx,ecx→**p,***p→eax

再简化为

**p+4→**p,***p→eax

注:(①)lea 0x4(%eax), %ecx 意思是取有效地址Load Effect Address,相比于mov 0x4(%eax), %ecx使用地址所指向的值*(eax+4)→ecx,lea指令只使用地址的值eax+4→ecx,少做一步。64位也是如此a。

(对于64位则是:

*p→rax,*rax→rax,rax+4→rcx,*p→rdx,rcx→*rdx,*rax→eax

可以简化为:

**p→rax,rax+4→rcx,rcx→**p,***p→eax

再简化为

**p+4→**p,***p→eax

看到数据流了,C语言语句自然也就呼之欲出了,即return (**p=**p+4,*(int*)**p)。(逗号,运算符的意思是从左到右计算式子,然后返回最后一个)

注意这里的+4指的是4个字节,而在64位32位中都一样,于是初步断定**p是固定大小类型变量,同时返回值是int类型的,故认为它(**p)是int,所以参数p的类型就是int**。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11668840.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-17
下一篇 2023-05-17

发表评论

登录后才能评论

评论列表(0条)

保存