对于一元运算,我们现在指的还不是函数(完成函数会在以后讲到),而是一般语言中内置的一元运算,比如Scheme中的add1,sub1,integer->char, char->integer, fixnum? ,boolean? ,null? ,char? 等的运算.

实现这种一元运算的原理和关键就在于用汇编语言完成这些函数的运算后,我们可以使用%eax寄存器将运算的结果进行返回.

1 修改Scheme编译主程序

我们要将编译程序调整为适应一元运算

(define (compile-program expr)(emit-head)(emit-expr expr)(emit-return))

从我们之前的经验大概可以看出来,汇编语句中只有一些是于我们所要编写的程序相关的,所以我们可以把编译主程序改写为由head,expr,return三部分组成的程序.

Head:

(define (emit-head)(emit " .text")(emit " .global _scheme_entry")(emit " .def _scheme_entry; .scl 2; .type 32; .endef")(emit "_scheme_entry:")(emit "LFB0:")(emit " .cfi_startproc")(emit " pushl %ebp")(emit " .cfi_def_cfa_offset 8")(emit " .cfi_offset 5, -8")(emit " movl %esp, %ebp")(emit " .cfi_def_cfa_register 5"))

expr:

(define (emit-expr expr)(cond ((immediate-value? expr)(emit-immediate expr))((primcall? expr)(emit-primcall expr))(else (error 'emit-expr))))

return:

(define (emit-return)(emit " popl %ebp")(emit " .cfi_restore 5")(emit " .cfi_def_cfa 4, 4")(emit " ret")(emit " .cfi_endproc")(emit "LFE0:"))

2 定义用于编写一元运算的宏

为了方便我们编写一元运算的汇编代码,我们可以写一个宏:

(define-syntax define-primitive(syntax-rules ()((_ (op arg* ...) b b* ...)(begin (putprop 'op '*is-prim* #t)(putprop 'op '*arg-length* (length '(arg* ...)))

(putprop 'op '*emitter* (lambda (arg* ...) b b* …))))))

3 完成一元运算的汇编代码

(define-primitive (add1 arg)(emit-expr arg)(emit " addl $~a, %eax" (immediate-value-rep 1)))

(define-primitive (sub1 arg)(emit-expr arg)(emit " subl $~a, %eax" (immediate-value-rep 1)))

(define-primitive (char->integer arg)(emit-expr arg)(emit " shll $~s, %eax" (- charshift fxshift)))

字符转换为数字只需要向右移动6位即可,

因为字符的低8位为00001111, 数字 的低8位为xxxxxx00

(define-primitive (integer->char arg)(emit-expr arg)(emit " shll $~s, %eax" (- charshift fxshift)))

(define-primitive (fixnum? arg)(emit-expr arg)(emit " and $~s, %al" fxmask)(emit-cmp fxtag))

(define-primitive (null? arg)(emit-expr arg)(emit-cmp list_nil))

(define-primitive (boolean? arg)(emit-expr arg)(emit " and $~s, %al" bool_mask)(emit-cmp bool_f))

判断是否是布尔值是利用bool_mask(0xbf),将#t转变为#f,然后比较是否等于#f

(define-primitive (char? arg)(emit-expr arg)(emit " and $~s, %al" charmask)(emit-cmp chartag))

最后是判断是否相等的汇编代码:

(define (emit-cmp tag)(emit " cmp $~s, %al" tag)(emit " sete %al")(emit " movzbl %al, %eax")(emit " sal $~s, %al" bool_bit)(emit " or $~s, %al" bool_f))

通过sete我们可以将比较结果放置在%eax中,如果相等,为1,否则为0,

将1左移6位后,与bool_f或运算为bool_t,若为0,或运算后仍为bool_t.

转载于:https://www.cnblogs.com/zhangfann/p/4350353.html

用Scheme写Scheme编译器(三):一元运算相关推荐

  1. 从零写一个编译器(三):语法分析之几个基础数据结构

    项目的完整代码在 C2j-Compiler 写在前面 这个系列算作为我自己在学习写一个编译器的过程的一些记录,算法之类的都没有记录原理性的东西,想知道原理的在龙书里都写得非常清楚,但是我自己一开始是不 ...

  2. 学了编译原理能否用 Java 写一个编译器或解释器?

    16 个回答 默认排序​ RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和 ...

  3. 从零写一个编译器(完结):总结和系列索引

    前言 这个系列算作我自己的学习笔记,到现在已经有十三篇了,加上这篇一共十四篇.一步一步的从词法分析到语法分析.语义分析,再到代码生成,准备在这一篇做一个总结收尾和一个这个系列以前文章的索引. (另外, ...

  4. 从零写一个编译器(一):输入系统和词法分析

    项目的完整代码在 C2j-Compiler 前言 从半抄半改的完成一个把C语言编译到Java字节码到现在也有些时间,一直想写一个系列来回顾整理一下写一个编译器的过程,也算是学习笔记吧.就从今天开始动笔 ...

  5. 编译器入门 语法分析器 java_从零开始写个编译器吧 - Parser 语法分析器

    Parser(语法分析器)的编写相对于 Tokenizer (词法分析器)要复杂得多,因此,在编写之前可能也会铺垫得更多一些.当然,本系列旨在"写出"一个编译器,所以理论方面只会简 ...

  6. 精读《手写 SQL 编译器 - 回溯》

    摘要: 1 引言 上回 精读<手写 SQL 编译器 - 语法分析> 说到了如何利用 Js 函数实现语法分析时,留下了一个回溯问题,也就是存档.读档问题. 我们把语法分析树当作一个迷宫,有直 ...

  7. 【Scheme】Scheme 编程学习 (二) —— 基础

    [Scheme]Scheme 编程学习 (二) -- 基础 文接前一节内容 : [Scheme]Scheme 编程学习(一) -- 概述 本文章可以跟视频课程一起看,做了一些补充说明 原视频地址: B ...

  8. 精读《手写 SQL 编译器 - 错误提示》

    1 引言 编译器除了生成语法树之外,还要在输入出现错误时给出恰当的提示. 比如当用户输入 select (name,这是个未完成的 SQL 语句,我们的目标是提示出这个语句未完成,并给出后续的建议: ...

  9. 精读《手写 SQL 编译器 - 文法介绍》

    1 引言 文法用来描述语言的语法规则,所以不仅可以用在编程语言上,也可用在汉语.英语上. 2 精读 我们将一块语法规则称为 产生式,使用 "Left → Right" 表示任意产生 ...

最新文章

  1. 诚意租房网blog2
  2. FTP服务(vsftpd)配置
  3. 检测未定义的对象属性
  4. android_launcher的源码详细分析
  5. 酱油和gbt酱油哪个好_酱油不是越贵越好,聪明人才知道的两个选酱油小技巧
  6. 剖析Caffe源码之Net---Net构造函数
  7. 操作vsam用sequential访问模式REWRITE数据
  8. CV学习笔记-Alexnet
  9. 耐思尼克域名注册:通过icann之后和之前的那些小故事
  10. STK MATLAB联合仿真(一)STK与MATLAB的连接(COM与Connector)
  11. 微信内置浏览器cookie设置问题
  12. socks v5 协议解析
  13. 给初中生的量子力学学习指南
  14. android相机固定焦距,android Camera 设置焦距
  15. java-net-php-python-springboot羽毛球场地管理系统演示录像计算机毕业设计程序
  16. 计算机无法获取正常的ip地址,无法获取ip地址,教您电脑无法获取ip地址的解决方法...
  17. 高德地图开发 —— 获取高德地图开发的 key
  18. 内存换CPU CPU换内存例子
  19. Python的多线程和多进程教程:大大提高效率
  20. 【面经】国信证券数据清算工程师面经

热门文章

  1. 约瑟夫环循环队列问题java_java 实现约瑟夫环
  2. 因分辨率变化html页面布局跳动_Web前端页面设计流程及注意事项,谨记!
  3. R语言重抽样与自助法
  4. 王益:分布式机器学习的故事
  5. 文件被后台程序占用无法删除_群晖NAS教程第十五节:查询群晖NAS硬盘空间占用情况,解决删除文件空间不增加问题...
  6. 系统学习NLP(九)--中文分词算法综述
  7. 目标检测(十八)--FPN
  8. 系统学习机器学习之随机场(五)--CRF++源码L-BFGS算法补充
  9. Regularized least-squares classification(RLSC)
  10. 编译原理教程_7 语法制导的语义计算