【问题标题】:Assembly input-output装配输入输出
【发布时间】:2015-04-21 09:28:42
【问题描述】:

我有 2 个程序:其中一个执行输入输出(C++),另一个计算公式(Assembly)。他们互相合作。

这个程序做输入输出:

#include <iostream>

using namespace std;

extern "C" int calc(int a, int b, int c, int d);

int main()
{
    int a;
    cout<<"a:"<<endl;
    cin>>a;
    cout<<"b:"<<endl;
    int b;
    cin>>b;
    cout<<"c:"<<endl;
    int c;
    cin>>c;

    cout<<"d:"<<endl;
    int d;
    cin>>d;

    int calculation = calc(a,b,c,d);
    cout << "5*a-c*d+7*b-2=" <<calculation<< endl;
    return 0;
}

这个程序计算结果:

format ELF

public calc

calc: 
    push    ebp
    mov ebp, esp
label a dword at ebp+8
label b dword at ebp+12
label c dword at ebp+16
label d dword at ebp+20

mov eax, [a]
mov ebx, 5
mul ebx
mov ecx, eax

mov eax, [c]
mov ebx, [d]
mul ebx
sub ecx, eax


mov eax, [b]
mov ebx, 7
mul ebx
add eax, ecx

sub eax, 2
mov esp, ebp
pop ebp     
ret         

你能帮我在汇编中也做输入输出吗(没有 C++ 程序)?我不知道如何在这个例子中做到这一点。 感谢任何帮助。

【问题讨论】:

  • 您想使用什么汇编程序(FASM?)?您是如何组装、编译和链接这两个程序的?
  • @rkhb 我使用 fasm,编译两个程序我使用 ' g++ -m32 calc.cpp calcul.o -o a.out'

标签: assembly io fasm


【解决方案1】:

在汇编中手动编程cincout 几乎是不可能的。但是您可以使用 C 库的函数 printfscanf,它是 C++ 标准的子集:

format ELF
public main
extrn printf
extrn scanf
extrn fflush

section '.text' executable

calc:
label .a dword at ebp+8                 ; Labels with dot are local labels
label .b dword at ebp+12
label .c dword at ebp+16
label .d dword at ebp+20

    push ebp
    mov ebp, esp

    mov eax, [.a]
    mov ebx, 5
    mul ebx
    mov ecx, eax
    mov eax, [.c]
    mov ebx, [.d]
    mul ebx
    sub ecx, eax
    mov eax, [.b]
    mov ebx, 7
    mul ebx
    add eax, ecx
    sub eax, 2

    mov esp, ebp
    pop ebp
    ret

main:
label .calculation dword at ebp-4       ; Labels with dot are local labels
label .a dword at ebp-8
label .b dword at ebp-12
label .c dword at ebp-16
label .d dword at ebp-20

    push ebp
    mov ebp, esp
    sub esp, 20                         ; Space for the local variables

    lea eax, [in_msg]
    push eax
    call printf                         ; printf ("a: ");
    add esp, 4

    lea eax, [.a]                       ; Pointer to .a (effective address of .a)
    push eax
    push scan_fmt
    call scanf                          ; scanf (" %d", &a);
    add esp, 8                          ; Clean up the stack

    lea eax, [in_msg+4]
    push eax
    call printf                         ; printf ("b: ");
    add esp, 4

    lea eax, [.b]                       ; Pointer to .a (effective address of .a)
    push eax
    push scan_fmt
    call scanf                          ; scanf (" %d", &b);
    add esp, 8                          ; Clean up the stack

    lea eax, [in_msg+8]
    push eax
    call printf                         ; printf ("c: ");
    add esp, 4

    lea eax, [.c]                       ; Pointer to .a (effective address of .a)
    push eax
    push scan_fmt
    call scanf                          ; scanf (" %d", &c);
    add esp, 8                          ; Clean up the stack

    lea eax, [in_msg+12]
    push eax
    call printf                         ; printf ("d: ");

    add esp, 4
    lea eax, [.d]                       ; Pointer to .a (effective address of .a)
    push eax
    push scan_fmt
    call scanf                          ; scanf (" %d", &d);
    add esp, 8                          ; Clean up the stack

    push [.d]                           ; Call by value
    push [.c]                           ; Call by value
    push [.b]                           ; Call by value
    push [.a]                           ; Call by value
    call calc                           ; EAX = calc (a,b,c,d)
    add esp, 16                         ; Clean up the stack
    mov [.calculation], eax             ; Store result for later use

    push [.calculation]
    push out_fmt
    call printf                         ; printf("5*a-c*d+7*b-2=%d\n",calculation);
    add esp,8                           ; Clean up the stack

    leave
    ret

section '.data' writeable

    out_fmt     db "5*a-c*d+7*b-2=%d", 10, 0
    scan_fmt    db " %d",0
    in_msg      db "a: ",0,"b: ",0,"c: ",0,"d: ",0

组装、链接并运行它

fasm calc.asm
g++ -m32 -o calc calc.o
./calc

您可以使用gcc,而不是g++

【讨论】:

    【解决方案2】:

    您可以在汇编代码中使用 C 库 (libc) 中的函数。如何调用 C 函数的详细信息取决于使用的汇编程序。此外,哪些寄存器和/或堆栈用于函数参数以及使用顺序取决于可执行目标(32 位或 64 位)。例如在 64 位 Linux 上调用 scanf 函数的 yasm 汇编语法可以是:

    segment .data
    format:  db  "%d"  ;format string used in scanf("%d", &var)
    var: dd 123    ;variable where we want to read input to (initialized to a random number 123)
    segment .text
    global main
    extern scanf
    main:
    lea rax, [var]
    lea edi, [format]
    xor eax, eax
    call  scanf
    

    为了生成可执行文件:

    • yasm -f elf64 usingClib.s
    • gcc usingClib.o -o usingClib

    我建议使用gcc 而不是ld 作为 gcc 默认链接 C 库。

    【讨论】:

      猜你喜欢
      • 2013-07-04
      • 2013-07-05
      • 1970-01-01
      • 2012-12-02
      • 1970-01-01
      • 1970-01-01
      • 2016-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多