- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我尝试过从 C 调用 ASM,反之亦然。至少目前它运行完美,但我有疑问。这是我的代码:
test.S 紧随其后:
.text
.global _start
.global _main
.type _main, @function
.global writeMe
.type writeMe, @function
_start:
#; Write hello world for 5 times.
#; Jump exit and call C function after that.
#; C function calls writeMe assembly function
#; Exit with syscall
xorl %ecx, %ecx #; ecx = 0
call _get_eip #; get eip without labels. Just for research.
pushl %eax #; push to stack
incl %ecx #; ++ecx
pushl %ecx #; push to stack
movl $len,%edx #; tell length of string
movl $msg,%ecx #; tell string position
movl $1,%ebx #; fd = stdout
movl $4,%eax #; syscall = write
int $0x80 #; perform call
popl %ecx #; pop counter
movl %ecx, %eax #; eax = ecx
cmpl $0x5, %eax #; compare 0x5 and eax
je _exit #; eax == 0x5, jump exit
_jmp:
popl %eax #; pop instruction pointer
jmpl %eax #; jmp
_exit:
call _main #; call C function
movl $0,%ebx #; EXIT_SUCCESS
movl $1,%eax #; syscall = exit
int $0x80 #; perform call
ret
_get_eip: #; function for getting eip
popl %eax #; pop eip
pushl %eax #; push again to return
ret #; return location
writeMe: #; function for writing, called from C
popl (__eip) #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
movl $1, %ebx #; fd = stdout
movl $4, %eax #; syscall = write
int $0x80 #; perform call
pushl (__eip) #; push return location
ret #; return location
writeMe2: #; function for writing, called from C
popl %ecx #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
movl $1, %ebx #; fd = stdout
movl $4, %eax #; syscall = write
int $0x80 #; perform call
subl $0x0C, %esp #; restore stack
ret
.data
__eip: .long
msg:
.ascii "Hello, world!\n\0"
len = . - msg
main.C 紧随其后:
extern void writeMe(const char *msg, int len);
int _strlen(const char *msg) {
int _len = 0;
while (*msg++ != 0x0)
_len++;
return _len;
}
void _main() {
const char * szmsg = "Hello, world!\n";
writeMe(szmsg, _strlen(szmsg));
}
我的输出与我预期的一样。
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
我的问题如下:
1)
.type writeMe, @function
这段代码是什么意思? “GCC”的信息?它有什么作用?我必须这样做吗?
2)
我必须写这个通知操作吗?如果函数在 C 文件中声明?
.type _main, @function
_main 在C 文件中声明,我必须写吗?
3)
popl (__eip) #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
........
pushl (__eip) #; push return location
我在 writeMe 中使用过这段代码,它安全吗?换句话说,我可以弹出参数,还是 GCC 会自动弹出它?
popl %ecx #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
....
subl $0x0C, %esp #; restore stack
我在第二个函数中使用了这段代码。我问你,哪一个是安全正确的?
4)从 C 调用汇编函数后是否需要恢复寄存器?(我听说我必须恢复 EDI,但其他人呢?)
感谢您的所有回复。
最佳答案
1) 设置函数的符号类型。不需要,除非在特殊情况下,例如共享库。
2) 不,编译器已经为 C 中定义的函数完成了。
3) 这两个都是错误的。您应该访问相对于 esp
的参数,或者在设置标准堆栈框架之后,相对于 ebp
。
4) 您应该阅读相应的 ABI 文档以获取有关调用约定的信息。通常,您可以使用 eax
、ecx
和 edx
,其余部分必须保留。
关于c - 关于从 Assembly 调用 C 函数,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31464610/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!