在 ASM 中返回函数结果

admin 2024年11月25日23:20:03评论9 views字数 2169阅读7分13秒阅读模式

首先讲一下 C 的库函数 fgets()。

char *fgets(char *str, int n, FILE *stream);
  • str:指向存储输入字符串的缓冲区的指针。

  • n:要读取的最大字符数(包括终止符 )。

  • stream:输入流,通常是 stdin。

fgets 函数会读取最多 n-1 个字符,并在末尾添加一个空字符 。如果读取的行包含换行符 n,fgets 也会将其也包含在内。

如果成功,返回指向字符串的指针。如果到达文件末尾或者没有读取到任何字符,则返回空指针。

假设用户输入了一行文本 "Hello Worldn",fgets 会读取并存储如下内容:

str = "Hello Worldn"

为了去掉换行符,需要找到字符串的最后一个字符,并将其替换为 。

首先计算字符串的长度:

char* result = fgets(dest, maxLen, stdin);int len = strlen(result);

strlen 函数返回字符串的实际长度,不包括终止符 。对于 "Hello Worldn",strlen 返回 12。

然后检查是否有换行符:

if (len > 0 && result[len - 1] == 'n') {    result[len - 1] = '';}
  • len > 0 确保字符串非空。

  • result[len - 1] == 'n' 检查字符串的最后一个字符是否是换行符。

  • 如果是换行符,将其替换为 



下方的 C++ 代码是一个与汇编语言代码交互的例子。定义了一个 readLine 函数来读取用户输入,并调用了汇编语言定义的 asmMain 和 getTitle 函数。

// 源.cpp#include <stdio.h>#include <string.h>
extern "C" { void asmMain(void); char* getTitle(void); int readLine(char* dest, int maxLen);};
// 第一个参数 rcx 提供,第二个参数 rdx 提供int readLine(char* dest, int maxLen) { char* result = fgets(dest, maxLen, stdin);    if (result != NULL) { // 删除字符串末尾的换行符 int len = strlen(result);        if (len > 0 && result[len - 1] == 'n')        { dest[len - 1] = 0; }        return len;    } return -1;}
int main(void) { char* title = getTitle(); printf("%s startn", title);    asmMain(); printf("%s end", title);}
  • getTitle() 函数(汇编提供),返回一个指向包含程序标题的字符串指针,由 C++ 代码打印这个标题。

  • readLine() 函数(C++ 提供),汇编代码可以调用该函数从用户处读取一行文本,然后放入字符串缓冲区中(下方汇编代码的 input)。


怎么放入缓冲区?readLine 函数使用 fgets 从标准输入读取一行文本,并将其存储在 dest 指向的缓冲区中。如果读取成功,它会去掉最后一行的换行符,并返回读取的字符数;如果读取失败,则返回 -1。



下方的汇编代码,定义了数据段(.data)和代码段(.code),并且使用了外部定义的两个过程 printf 和 readLine。这个程序的主要功能是提示用户输入一个字符串,并将该字符串显示出来。

    option casemap:none
maxLen = 256
.datatitleStr byte 'Calling Asm', 0prompt byte 'Enter a string: ', 0fmtStr byte 'User enter: %s', 10, 0
input byte maxLen dup (?);maxLen dup (?) 操作数指示 MASM 复制 maxLen 个字节;每个字节都未被初始化
    .codeexterndef printf:procexterndef readLine:proc
;getTitle 返回 titleStr 字符串的地址;通过 lea 指令加载 titleStr 的地址到 rax 寄存器中,然后返回 public getTitlegetTitle proc lea rax, titleStr ;在函数调用过程中,rax 可用于存储函数的返回值 ;当一个函数执行完成并需要返回一个值时,这个返回值通常会被放在RAX寄存器中 retgetTitle endp
public asmMainasmMain proc sub rsp, 56 lea rcx, prompt call printf
mov input, 0 ;将 input 的第一个字节设置为0,相当于清空缓冲区,确保输入的字符串以0结尾 lea rcx,input mov rdx, maxLen call readLine ;调用 readLine 函数从标准输入读取一行文本到 input 中 ;寄存器 RCX 传递 input 的地址,RDX 传递最大允许输入的长度 maxLen。
lea rcx, fmtStr lea rdx, input call printf
add rsp, 56 retasmMain endp end

在 asmMain(); 处达断点。

在 ASM 中返回函数结果

正常运行。

在 ASM 中返回函数结果

原文始发于微信公众号(走在网安路上的哥布林):在 ASM 中返回函数结果

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月25日23:20:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   在 ASM 中返回函数结果https://cn-sec.com/archives/3437125.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息