【问题标题】:get a char passed as parameter获取作为参数传递的字符
【发布时间】:2021-02-23 18:49:13
【问题描述】:

我想在 NASM System V ABI x86-64(英特尔语法)中编写一个可以在 C 程序中使用的函数。

这是函数的原型:

char *rindex(const char *s, int c);

因此我按顺序检索参数(const char *s = rdi, int c = rsi

首先,我将寄存器rsi中存储的字符放入ah

segment .text

global rindex:function

rindex:
    mov ah, byte [rsi] ;; get the character
    [...]

不幸的是,这行代码使我的程序崩溃了:

rindex("hello world", 'o') // segfault

为什么无法获取 char,正确的方法是什么?

【问题讨论】:

  • Char 由 rdi 指向,而不是 rsi。
  • 我认为参数应该按以下顺序传递:rdirsirdxrcx。不是这样吗?

标签: linux assembly x86-64 nasm calling-convention


【解决方案1】:

我将您的第一个参数 (const char *s = rdi) 称为“char”,因为它是指向 char 的指针。您的第二个参数 (int c = rsi) 是 int。要访问s 指向的字符串的元素,您可以使用mov ah, byte ptr [rdi]。但是您的第二个参数不是指针,rsi 包含c 的值。要读取它,您可以从 esi 读取,因为 int 的值适合 rsi 的低 32 位。

【讨论】:

  • 确实,字符存储在al,谢谢!
  • 所以它只是一个int,它的值总是在0到256之间,即低字节。您不必将它移动到任何地方,您可以在它所在的位置访问它作为 8 位 sil 寄存器。例如,cmp [rdi], sil 查看第一个字节是否匹配。
  • mov rax, rsi 将复制 64 位,包括 ESI 中 32 位 int 值之上的可能非零垃圾。如果您只想对低 8 位进行零扩展,movzx eax, sil(诸如 strchr 之类的 C 函数将 char 作为 int 的底部,这就是 OP 将其称为“char”的原因)。或者像 Nate 说的,直接在 SIL 中使用即可。
  • @Midway @NateEldredge 当第二个参数是一个值始终在0到255之间的int时,将其声明为char不是更好吗?
  • @PeterCordes strchr 和其他字符串函数具有int 类型的字符参数的事实总是让我感到困惑。
猜你喜欢
  • 1970-01-01
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多