本章目的:
- 实现用户键盘的输入与显示输出
- 掌握C调用汇编程序传参方法
一、准备工作
- Win7环境
- Bochs
- gcc,ld,nasm等
代码架构如下:
env和 tools里是一些编译开发工具。
代码托管在:
gitee.com/xundh/learn-os
二、C调用汇编的方法
1. 汇编显示字符、清屏等子程序
[BITS 16]global io_hltglobal clear_screenglobal read_char;global print_char;global print_str;global shutdown;; 清屏clear_screen: MOV ax, 03h INT 10hRET; 系统挂起io_hlt:HLTRET; 读一个字符到在AL中read_char: MOV ah,0x00 INT 0x16 RET; 打印AL中的字符print_char: MOV AL,[esp+4]print_char_al: MOV AH,0x0e INT 0x10 CMP al, 0x0d ; 是不是回车 JNE not_cr ; 不是 MOV al, 0x0a ; 输出换行 INT 0x10 ; output the LF not_cr: RET; 打印字符串的子程序,这里没有使用13H的BIOS子功能,而是使用循环显示单个字符的方法,以后再优化print_str: MOV edx,[esp+8] ;len MOV SI,[esp+4] ;msgprint: MOV AL, [SI] ADD SI, 1 CMP AL, 0 ; 字符串有没有读完,到0结束 DEC EDX JE end_print ; 跳到结束程序 MOV AH, 0x0e ; 显示一个字符 MOV BX, 15 ; 指定颜色 INT 0x10 ; 调用BIOS功能显示字符 CMP AL, 0x0d JNE not_cr_0 MOV AL, 0x0a ; 输出换行 INT 0x10 MOV BH, 0x00 ; 下面要把光标移到头部,但没起作用,以后再看是怎么回事 MOV AH, 0x02 MOV DH, 0x01 MOV DL, 0x01 INT 0x10not_cr_0: JMP printend_print: RET; 关机,尚未调用shutdown: MOV AX, 5301H ;Function 5301h: APM Connect real-mode interface XOR BX, BX ;Device ID: 0000h (=system BIOS) INT 15H ;Call interrupt: 15h MOV AX, 530EH ;Function 530Eh: APM Driver version MOV CX, 0102H ;Driver version: APM v1.2 INT 15H ;Call interrupt: 15h MOV AX, 5307H ;Function 5307h: APM Set system power state MOV BL, 01H ;Device ID: 0001h (=All devices) MOV CX, 0003H ;Power State: 0003h (=Off) INT 15H ;Call interrupt: 15h RET
2. 定义头文件供C语言调用:
#ifndef __UTILITIES_H_#define __UTILITIES_H_// 此处只提供函数声明void io_hlt(void);void clear_screen(void);char read_char(void);void print_char(char);void print_str(char *msg,int len);#endif
3. C获取汇编返回值的方法
- read_char的返回变量直接通过AX传递给C
4. 汇编获取C参数的方法
- 传入C的变量,使用下面的方法获取到C的参数:
print_str: MOV edx,[esp+8] ;len MOV SI,[esp+4] ;msg
运行效果:
输入字符后,屏幕即可回显输入的字符。按回车也可以实现换行。