15.3 翻译 Pcode 中的 readint 命令
readint 命令的翻译和 print 命令的翻译方法差不多,也需要利用 C 语言编写库函数。以下为相关的代码:
测试代码 test.nasm :
- readint "Please input an number: "
- print "Your input is: %d"
- exit 0
readint 宏,在 macro.inc 文件中:
- %MACRO readint 1
- [SECTION .DATA]
- %%STRING: DB %1, 0
- [SECTION .TEXT]
- PUSH DWORD %%STRING
- CALL READINT
- MOV [ESP], EAX
- %ENDMACRO
- EXTERN PRINT, READINT
READINT 库函数,在 tio.c 文件中:
- int STRLEN(char *s);
- int SYS_READ(char *buf, int len);
- int READINT(char *prompt) {
- char buf[BUFLEN], *p = buf, *p_end;
- SYS_PRINT(prompt, STRLEN(prompt));
- int len = SYS_READ(buf, BUFLEN-1), value = 0, negative = 0;
- p_end = buf + len + 1;
- while (p != p_end) {
- if (*p == ' ' || *p == '\t') {
- p++;
- } else {
- break;
- }
- }
- if (p != p_end && *p == '-') {
- negative = 1;
- p++;
- }
- while (p != p_end) {
- if (*p <= '9' && *p >= '0') {
- value = value * 10 + *p - '0';
- *p++;
- } else {
- break;
- }
- }
- if (negative) {
- value = -value;
- }
- return value;
- }
- int STRLEN(char *s) {
- int i = 0;
- while(*s++) i++;
- return i;
- }
- int SYS_READ(char *buf, int len) {
- __asm__(
- ".intel_syntax noprefix\n\
- PUSH EBX\n\
- PUSH ECX\n\
- PUSH EDX\n\
- \n\
- MOV EAX, 3\n\
- MOV EBX, 2\n\
- MOV ECX, [EBP+4*2]\n\
- MOV EDX, [EBP+4*3]\n\
- INT 0X80\n\
- \n\
- POP EDX\n\
- POP ECX\n\
- POP EBX\n\
- .att_syntax"
- );
- }
makefile 文件:
- test: test.o libtio.a
- ld -m elf_i386 -o test test.o -L. -ltio
- run: test
- ./test
- test.o: test.nasm macro.inc
- nasm -f elf32 -P"macro.inc" -o test.o test.nasm
- libtio.a: tio.c
- gcc -m32 -c -o tio.o tio.c
- ar -crv libtio.a tio.o
- clean:
- rm test.o test tio.o libtio.a
将以上四个文件下载下来放到用一个目录,输入 make run 即可编译并运行测试代码。运行过程如下:
- $ make run
- ...
- ./test
- Please input an number: 15
- Your input is: 15