⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 汇012.txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 2 页
字号:
考虑到C语言与汇编语言的接近程度,在此只介绍这二种程序设计语言之间的接口问题。

了解的内容:C语言源程序生成汇编语言的源程序的方法,从所生成的汇编语言源程序中,看出C语言语句用汇编语言实现的技巧,从而对C语言语句的语义有一个更进一步的理解。

掌握的内容:C语言函数参数的传递方法,在汇编语言中读取C语言函数参数的方法。

建议学习时间:2小时。
第12章 汇编语言和C语言
C/C++语言是一个被广泛使用的程序设计语言,它不仅具有良好的高级语言特征,而且还具有一些低级语言的特点,如:寄存器变量、位操作等。所以,C语言的程序与汇编语言程序之间能很平滑地衔接。另外,目前主要的C语言程序开发环境,如:Turbo C/C++、Borland C/C++等,也都提供了很好的混合编程手段。 

本章主要介绍汇编语言和C语言的混合编程和调用方法。虽然其它高级语言,如:Pascal、Basic等,也可与汇编语言混合使用,但出于其应用范围的考虑,不再对它们进行介绍,感兴趣的读者可参阅有关技术资料。

12.1 汇编指令的嵌入
为了提高C语言程序内某特殊功能段的处理效率,我们可以在其源程序中嵌入一段汇编语言程序段。这样做,虽然能达到提高了程序处理效率的目的,但它无疑以丧失源程序的可移植性为代价。所以,当想用C语言和汇编语言混合编程时,程序员需要权衡采用这种方法的利与弊。 

在C语言中,嵌入汇编语言的语法如下(*): 

asm <opcode> <operands> <; or newline> 

注意:这里的分号';'不是汇编语言中起注释作用的分号,而是作为语句的分隔符。 

若C语言源程序中嵌入一条汇编语句,则可按下列方式来做: 

asm mov ax, data 

若要嵌入一组汇编语句,则需要用括号'{'和'}'把它们括起来。 

asm {
   mov ax, data1
   xchg ax, data2
   mov data1, ax     //实现整型变量data1和data2之值的交换
} 

例12.1 在C语言源程序中嵌入汇编语言语句实现赋值语句A=A+B+C,其中:A、B、C都是整型变量。 

解: …… 

asm {push ax      //实现整型变量A=A+B+C
  mov ax, A
  add ax, B
  add ax, C
  mov A, ax
  pop ax
} 
12.2 C语言程序的汇编输出
在Turbo C++或Borland C++编程环境下,我们可TCC或BCC行命令把一个C语言的源程序转换成汇编语言的源程序。通过阅读汇编语言程序可以很准确地知道C语言语句的功能是如何实现的,这样,可为将来学习《编译原理》课程中的"寄存器调度"和"代码生成"等相关知识打下良好的基础。

C语言源程序转换的命令格式如下:

TCC -S t1.cpp 或 BCC -S t1.cpp   ;假设其文件名为t1.cpp

若命令TCC/BCC不带参数的话,则将显示其使用方法。

下面是C语言程序及其相对应的汇编语言程序,希望读者能逐行对照理解它们语句之间的转换关系,这将能进一步理解高级语言的语句功能。

1、C语言程序清单 

#include <stdio.h>
int sum(int a, int b, int c)
 {
  return (a+b+c);
 }
void main()
{int a, b, c;
 a = b = 12;
 c = 32;
 printf("%d", sum(a,b,c));
} 

2、生成的汇编语言程序清单

 ……                      ;一系列辅助说明信息 
 _TEXT segment byte public 'CODE'      ;代码段的开始 
 ;int sum(int a, int b, int c)           ;C语言语句  
       assume  cs : _TEXT
@sum$qiii proc  near            ;过程说明,对应于C语言sum过程
      push bp             ;为读取堆栈中的参数作准备,可参见第7.3.3节内容
      mov bp, sp 
 ;{
  ;return(a+b+c);  
       mov ax, word ptr [bp+4]
      add ax, word ptr [bp+6]
      add ax, word ptr [bp+8]
      jmp short @1@58
@1@58: 
 ;}  
       pop bp              ;sum子程序结束的代码
      ret
@sum$qiii endp 
 ;void main()       assume  cs : _TEXT
_main   proc  near             ;过程说明,对应于C语言中的主函数main()
      push bp
      mov bp, sp
      sub sp, 6 
 ;{int a, b, c;                  ;局部变量是用堆栈来存储的,请见第7.5.10节 
 ; a = b = 12;                  ;给局部变量赋值 
       mov ax, 12            ;用给堆栈单元赋值来实现对局部变量的赋值
      mov word ptr [bp-4], ax
      mov word ptr [bp-2], ax 
 ; c = 32;       mov word ptr [bp-6], 32 
 ; printf("%d", sum(a,b,c));            ;调用系统标准函数       push word ptr [bp-6]
      push word ptr [bp-4]
      push word ptr [bp-2]
      call near ptr @sum$qiii      ;用汇编语言形式调用自定义函数sum
      add sp, 6
      push ax
      mov ax, offset DGROUP : s@
      push ax
      call near ptr _printf        ;用汇编语言调用标准函数printf
      pop cx
      pop cx 
 ; }       mov  sp, bp            ;main子程序结束的代码
      pop  bp
      ret
_main   endp 
 _TEXT   ends                ;代码段的结束 
 _DATA   segment word public 'DATA'    ;数据段的定义
      s@ label byte
         db '%d'
         db 0
_DATA   ends 
 public  _main           ;下面说明函数的属性,请见第7.6.3节
public  @sum$qiii
extrn  _printf : near
_s@  equ s@
end
 12.3 简单的屏幕编辑程序 
下面是一个简单的屏幕编辑的C语言程序,它不仅涉及到键盘处理、光标定位、屏幕输出、字符颜色等,而且还运用了C语言和汇编语言的混合编程方法。若读者能把它改写成相同功能的汇编语言程序,那么,可以说,你已基本掌握了中断的使用方法,也对计算机输入输出的工作方式有了更进一步的认识。 

该程序的功能: 
◆ 可用移动光标键↑、↓、←和→移动光标1行或1列,也可用TAB/Shift+TAB、Home和End键跳跃地移动光标; 
◆ 当光标已在第1行,再向上移动时,这时,光标被定位到第25行,反之也然; 
◆ 当光标已在第0列,还要向左移动时,光标被定位到第79列,反之也然; 
◆ 当按下^W或^Z时,屏幕将向上或向下滚动1行; 
◆ 显示当前键盘的状态:大小写状态、数字键盘状态和插入/修改状态; 
◆ 如果按普通的键,将在屏幕上显示该字符,如果按下用Alt、Ctrl或Shift组合的组合键,则显示该按键的扫描码; 
◆ 用Esc键来结束程序的运行。 

C语言的源程序清单: 

#define NUM_KEY 0x20      /* 键盘状态字宏定义 */
#define CAPS_KEY 0x40
#define ESCAPE 27        /* 几个功能键的宏定义 */
#define TAB_KEY 9
#define SHIFT_TAB 15
#define CTRL_W 23
#define CTRL_Z 26
#define UP_ARROW 72
#define DOWN_ARROW 80
#define LEFT_ARROW 75
#define RIGHT_ARROW 77
#define INSERT 82
#define END_KEY 79
#define HOME_KEY 71
#define UP_SCROLL 6      /* 屏幕滚动宏定义 */
#define DOWN_SCROLL 7 

#include <dos.h>
int insert, cap_key, num_key; 

/* up_down:屏幕滚动方式:6-向上滚; 7-向下滚
 (l_row, l_col)-(r_row, r_col):滚动矩形的对角线坐标
 num:屏幕滚动的行数,0-清屏
 attr:滚动后所剩下行的属性 */
cls(int up_down, int l_row, int l_col, int r_row, int r_col, int num, int attr) 

{union REGS in, out;

 in.h.ah = up_down; in.h.al = num;
 in.h.ch = l_row;   in.h.cl = l_col;
 in.h.dh = r_row;   in.h.dl = r_col;
 in.h.bh = attr;
 int86(0x10, &in, &out);
}

  get_cursor(int *x, int *y)  /* 取当前光标的位置,并分别存入变量x和y中 */ 

{union REGS in, out;

 in.h.ah = 3; in.h.bh = 0;
 int86(0x10, &in, &out);
 *x = out.h.dh; *y = out.h.dl;
}

  locate(int row, int col)  /* 把光标设置在(row, col)位置 */ 

{union REGS in, out;

 in.h.ah = 2;  in.h.bh = 0;
 in.h.dh = row; in.h.dl = col;
 int86(0x10, &in, &out);
}

  disp_string(int row, int col, char string[])  /* 在(row, col)位置显示字符串string */ 

{struct REGPACK in, out;
 int x, y;

 get_cursor(&x, &y);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -