zoukankan      html  css  js  c++  java
  • 《汇编语言 基于x86处理器》第十三章高级语言接口部分的代码 part 2

    ▶ 书中第十三章的程序,主要讲了汇编语言和 C/++ 相互调用的方法

    ● 代码,汇编中调用 C++ 函数

     1 ; subr.asm
     2 INCLUDE Irvine32.inc
     3 
     4 askForInteger PROTO C
     5 showInt PROTO C, value:SDWORD, outWidth:DWORD
     6 
     7 OUTPUT_WIDTH = 8
     8 MAX_POWER = 10
     9 
    10 .data
    11 intVal DWORD ?
    12 
    13 .code
    14 SetTextOutColor PROC C, color:DWORD
    15     mov     eax, color
    16     call    SetTextColor
    17     call    Clrscr
    18     ret
    19 SetTextOutColor ENDP
    20 
    21 DisplayTable PROC C
    22     INVOKE askForInteger        ; 调用 C++ 函数输入整数
    23     mov    intVal, eax          ; 保存返回值
    24     mov    ecx, MAX_POWER
    25 
    26 L1: 
    27     push    ecx
    28     shl     intVal, 1                       ; 每次乘以 2
    29     INVOKE  showInt, intVal, OUTPUT_WIDTH   ; 调用 C++ 函数显示结果
    30     call    Crlf
    31     pop     ecx
    32     loop    L1
    33 
    34     ret
    35 DisplayTable ENDP
    36 
    37 END
     1 // main.cpp
     2 #include <iostream>
     3 #include <iomanip>
     4 using namespace std;
     5 
     6 extern "C"  // 声明外部 asm 过程和 C++ 函数
     7 {        
     8     void SetTextOutColor(unsigned color);   // 设置终端字体和背景颜色
     9     void DisplayTable();                    // 显示表格
    10     
    11     int askForInteger();                    // 输入整数
    12     void showInt(int value, int width);     // 按宽度 width 显示数字 value
    13 }
    14 
    15 int main()
    16 {
    17     SetTextOutColor(0x1E);                  // 蓝底黄字
    18     DisplayTable();
    19 
    20     getchar();
    21     getchar();
    22     return 0;
    23 }
    24 
    25 int askForInteger()
    26 {
    27     int n;
    28     cout << "Target integer [1, 90000]: ";
    29     cin >> n;
    30     return n;
    31 }
    32 
    33 void showInt(int value, int width)
    34 {
    35     cout << setw(width) << value;
    36 }

    ■ 输出结果

    ● 代码,汇编调用 C/C++ 库函数和自定义函数。有个奇怪的 bug,scanf 至少要在主函数中用一次,否则汇编的目标文件找不到,暂时不明。

     1 ; asmMain.asm
     2 INCLUDE Irvine32.inc
     3 
     4 printSingle PROTO C, aSingle:REAL4, precision:DWORD ; 声明外部函数(库函数不用声明)
     5 
     6 TAB = 9
     7 
     8 .code
     9 asmMain PROC C                              ; 程序入口
    10 
    11 .data                                       ; 测试 printf
    12 format BYTE "%.2f",TAB,"%.3f",0dh,0ah,0
    13 val1 REAL8 456.789
    14 val2 REAL8 864.231
    15 .code
    16 INVOKE printf, ADDR format, val1, val2      ; 调用 printf
    17                                             ; 书本注释曰,不能用 INVOKE ptrintf 来显示 REAL4 型变量?
    18 
    19 .data                                       ; 测试 scanf
    20 strSingle BYTE "%f",0
    21 strDouble BYTE "%lf",0
    22 float1 REAL4 1234.567
    23 double1 REAL8  1234567.890123
    24 
    25 .code
    26 INVOKE scanf, ADDR strSingle, ADDR float1   ; 调用 scanf,覆盖掉原本的值
    27 INVOKE scanf, ADDR strDouble, ADDR double1
    28 
    29 .data                                       ; 测试栈传参 printf 和自定义函数
    30 valStr BYTE "float1 in ASM = %.3f", 0dh, 0ah, 0
    31 
    32 .code
    33     fld    float1                           ; 将 float1 转存到 FPU 栈中
    34     sub    esp,8                            ; 指到栈的高位
    35     fstp    qword ptr [esp]                 ; 当成 double 取出
    36     push    OFFSET valStr                   ; 栈传参来调用 printf
    37     call    printf
    38     add    esp,12    
    39     INVOKE printSingle, float1, 3           ; 自定义外部函数来显示 float1
    40 
    41     call    Crlf        
    42     ret
    43 asmMain ENDP
    44 
    45 END
     1 // main.cpp
     2 #define _CRT_SECURE_NO_WARNINGS // 关闭 MVC++ 关于 scanf 被 scanf_s 取代的警告
     3 
     4 #include <stdio.h>
     5 #include <string>
     6 #include <strstream>
     7 
     8 using namespace std;
     9 
    10 extern "C"
    11 {
    12     void asmMain();
    13     void printSingle(float d, int precision);
    14 }
    15 
    16 void printSingle(float d, int precision)
    17 {
    18     strstream temp;
    19     temp << "float1 in C++ = %." << precision << "f" << '';
    20     printf(temp.str(), d);
    21 }
    22 
    23 int main()
    24 {
    25     asmMain();
    26     scanf("");  // 如果没有这一句就会报错:LNK2019,无法解析的外部符号 _scanf,该符号在函数 _asmMain 中被引用
    27     getchar();
    28     getchar();
    29     return 0;
    30 }

    ■ 程序输出

    456.79  864.231
    123.456
    123456789.123456789
    float1 in ASM = 123.456
    float1 in C++ = 123.456

    ● 代码,汇编调用 C 库函数,system 和 file 相关。还是有那个要在主函数里用一次 printf 和 scanf 的问题。

     1 ; asmMain.asm
     2 .586
     3 .MODEL flat, C
     4 
     5 system PROTO, pCommand:PTR BYTE                                 ; 声明一堆库函数
     6 printf PROTO, pString:PTR BYTE, args:VARARG
     7 scanf  PROTO, pFormat:PTR BYTE,pBuffer:PTR BYTE, args:VARARG
     8 fopen  PROTO, mode:PTR BYTE, filename:PTR BYTE
     9 fclose PROTO, pFile:DWORD
    10 
    11 BUFFER_SIZE = 5000
    12 .data
    13 str1 BYTE "cls", 0
    14 str2 BYTE "dir/w", 0
    15 str3 BYTE "Enter the name of a file: ", 0
    16 str4 BYTE "%s", 0
    17 str5 BYTE "Failed to open the file", 0dh, 0ah, 0
    18 str6 BYTE "Succeeded to open the file", 0dh, 0ah, 0
    19 modeStr BYTE "r",0
    20 
    21 fileName BYTE 60 DUP(0)
    22 pBuf  DWORD ?
    23 pFile DWORD ?
    24 
    25 .code
    26 asm_main PROC
    27     INVOKE  system,ADDR str1                    ; cls
    28     INVOKE  system,ADDR str2                    ; dir
    29     
    30     INVOKE  printf,ADDR str3                    ; 提示信息
    31     INVOKE  scanf, ADDR str4, ADDR fileName     ; 输入文件名
    32 
    33     INVOKE  fopen, ADDR fileName, ADDR modeStr  ; 尝试打开文件
    34     mov     pFile, eax
    35 
    36     .IF eax == 0
    37         INVOKE printf,ADDR str5
    38         jmp quit
    39     .ELSE
    40         INVOKE printf,ADDR str6
    41     .ENDIF
    42     INVOKE fclose, pFile
    43 
    44 quit:
    45     ret
    46 asm_main ENDP
    47 END 
     1 // main.cpp
     2 #define _CRT_SECURE_NO_WARNINGS
     3 #include <stdio.h>
     4 
     5 extern "C" void asm_main();
     6 
     7 void main()
     8 {
     9     asm_main();
    10     scanf("");
    11     printf("");
    12     getchar();
    13     getchar();
    14 }
  • 相关阅读:
    POJ2104 K-th Number Range Tree
    BZOJ 3390: [Usaco2004 Dec]Bad Cowtractors牛的报复(最大生成树)
    BZOJ 3391: [Usaco2004 Dec]Tree Cutting网络破坏(搜索)
    BZOJ 3412: [Usaco2009 Dec]Music Notes乐谱(离线处理)
    BZOJ 3410: [Usaco2009 Dec]Selfish Grazing 自私的食草者(贪心)
    BZOJ 3403: [Usaco2009 Open]Cow Line 直线上的牛(模拟)
    BZOJ 3402: [Usaco2009 Open]Hide and Seek 捉迷藏(最短路)
    BZOJ 3479: [Usaco2014 Mar]Watering the Fields(最小生成树)
    BZOJ 3432: [Usaco2014 Jan]Cross Country Skiing (二分+染色法)
    BZOJ 3299: [USACO2011 Open]Corn Maze玉米迷宫(BFS)
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9696552.html
Copyright © 2011-2022 走看看