15.3 翻译 Pcode 中的 readint 命令

readint 命令的翻译和 print 命令的翻译方法差不多,也需要利用 C 语言编写库函数。以下为相关的代码:

测试代码 test.nasm

  1. readint "Please input an number: "
  2. print "Your input is: %d"
  3. exit 0

readint 宏,在 macro.inc 文件中:

  1. %MACRO readint 1
  2. [SECTION .DATA]
  3. %%STRING: DB %1, 0
  4. [SECTION .TEXT]
  5. PUSH DWORD %%STRING
  6. CALL READINT
  7. MOV [ESP], EAX
  8. %ENDMACRO
  9. EXTERN PRINT, READINT

READINT 库函数,在 tio.c 文件中:

  1. int STRLEN(char *s);
  2. int SYS_READ(char *buf, int len);
  3.  
  4. int READINT(char *prompt) {
  5. char buf[BUFLEN], *p = buf, *p_end;
  6. SYS_PRINT(prompt, STRLEN(prompt));
  7. int len = SYS_READ(buf, BUFLEN-1), value = 0, negative = 0;
  8.  
  9. p_end = buf + len + 1;
  10.  
  11. while (p != p_end) {
  12. if (*p == ' ' || *p == '\t') {
  13. p++;
  14. } else {
  15. break;
  16. }
  17. }
  18.  
  19. if (p != p_end && *p == '-') {
  20. negative = 1;
  21. p++;
  22. }
  23.  
  24. while (p != p_end) {
  25. if (*p <= '9' && *p >= '0') {
  26. value = value * 10 + *p - '0';
  27. *p++;
  28. } else {
  29. break;
  30. }
  31. }
  32.  
  33. if (negative) {
  34. value = -value;
  35. }
  36.  
  37. return value;
  38. }
  39.  
  40. int STRLEN(char *s) {
  41. int i = 0;
  42. while(*s++) i++;
  43. return i;
  44. }
  45.  
  46. int SYS_READ(char *buf, int len) {
  47. __asm__(
  48. ".intel_syntax noprefix\n\
  49. PUSH EBX\n\
  50. PUSH ECX\n\
  51. PUSH EDX\n\
  52. \n\
  53. MOV EAX, 3\n\
  54. MOV EBX, 2\n\
  55. MOV ECX, [EBP+4*2]\n\
  56. MOV EDX, [EBP+4*3]\n\
  57. INT 0X80\n\
  58. \n\
  59. POP EDX\n\
  60. POP ECX\n\
  61. POP EBX\n\
  62. .att_syntax"
  63. );
  64. }

makefile 文件:

  1. test: test.o libtio.a
  2. ld -m elf_i386 -o test test.o -L. -ltio
  3.  
  4. run: test
  5. ./test
  6.  
  7. test.o: test.nasm macro.inc
  8. nasm -f elf32 -P"macro.inc" -o test.o test.nasm
  9.  
  10. libtio.a: tio.c
  11. gcc -m32 -c -o tio.o tio.c
  12. ar -crv libtio.a tio.o
  13.  
  14. clean:
  15. rm test.o test tio.o libtio.a

将以上四个文件下载下来放到用一个目录,输入 make run 即可编译并运行测试代码。运行过程如下:

  1. $ make run
  2. ...
  3. ./test
  4. Please input an number: 15
  5. Your input is: 15