如何将给定的check_password函数汇编代码反向翻译为等价C代码?
结论
你写的两个版本都不完全正确:版本2逻辑完全错误,版本1流程符合但存在C语言运算符优先级的致命坑,修正后即可得到正确等价代码。
汇编逻辑逐段对应
我们先明确汇编的执行流程:
- 初始化循环计数器
i=0 - 循环逻辑:
- 取全局数组
foo[i]和常量0x5f做异或运算 - 运算结果和输入字符串的第
i位s[i]比较 - 只要有一次不相等,直接返回整数值0
- 相等则
i++,直到i=10退出循环
- 取全局数组
- 10次校验全部通过后,判断
s[10]是否为\0,返回该判断的布尔结果(相等返回1,不等返回0)
两个版本的问题
版本2的错误点
- 校验失败分支逻辑错误:汇编校验不匹配直接返回0,不是返回
s[10]==0的结果 - 全量校验通过后返回值错误:汇编要求必须判断第11位是否为结束符,不能直接返回1
版本1的隐藏错误
流程走向符合汇编逻辑,但存在运算符优先级漏洞:C语言中!=的优先级高于位异或^,你写的foo[i] ^ 0x5f != s[i]会被编译器解析为foo[i] ^ (0x5f != s[i]),和你预期的(foo[i] ^ 0x5f) != s[i]逻辑完全不同,会直接导致校验功能失效。
正确的等价C代码
// 先声明全局数组foo,该定义在其他编译单元 extern char foo[10]; int check_password (char *s) { for (int i = 0; i != 10 ; i++) { // 必须加括号明确运算优先级 if ((foo[i] ^ 0x5f) != s[i]) return 0; } return s[10] == '\0'; }
关于你疑惑的字符串长度问题
这段汇编的设计本身就要求输入的字符串s至少长度为11:前10位是密码校验位,第11位必须是C字符串结束符\0。如果输入是严格10字节的非\0结尾的内容,会触发越界访问,这是原汇编代码的固有逻辑,不是翻译导致的问题。
内容的提问来源于stack exchange,提问作者user16011868
相关产品推荐
相关产品推荐

