kvmtool下载编译

git clone https://github.com/kvmtool/kvmtool.git 下载后进入到目录执行make即可。

补码

计算机怎么表示负数?以四位有符号数为例,使用高位作为符号位,最高位为0表示正数,为1表示负数,其余三位用来表示值。在计算机中,我们将这种表示方式称为原码。例如:

十进制 二进制 十进制 二进制
2 0010 -2 1010

使用原码表示时,数字0有两种编码:0000和1000。因此,如果使用原码,在设计系统时就需要额外的电路区分+0和-0更糟糕的是如果一个数的正数相加应为0,2 - 2为例:2 - 2 = 2 + (-2) = 0010 + 1010 = 1100 = -4 这明显不对,也就是说,原码不能正确计算减法。怎么办呢?聪明的人类发现使用补码表示数字就可以加减法了。

即:正数的反码和补码都是原码,负数的反码是除符号位以外按位取反,补码是在反码基础上+1。使用补码重新计算 2 - 2:2 + (-2) = 0010 + 1110 = 0000

ASCII码

计算机用高低电平分别表示0和1,所有的数据在存储和运算时都要使用二进制表示,如果我们想用数字表示文本,就要对每一个文本进行编码,目的就是文本转换成数值。具体用哪些二进制是数字表示哪个符号,美国国家标准协会制定了美国信息交换标准代码(American Standard Code for Information Interchange)简称ASCII。ASCII使用8位编码,最多可以表示256个字符,hello world使用的编码就是为:68 65 6C 6C 6F 77 6F 72 6C 64

写外设指令

操作码 指令 描述
EE out DX,AL 将寄存器AL中的字节输出到寄存器DX中的I/O端口地址

第一列为操作码,第二列为汇编语法描述的指令,第三列是指令意义的详细描述。从描述中我们可以得到,EE操作码它会自动到寄存器AX中读取源操作数,到寄存器DX中读取目的操作数。out为操作码的助记符,AL为8位寄存器,DX是16位寄存器,ASCII码是8位的,串口的地址0x3F8(IBM计算机外设地址)是需要使用16位的表示的。

根据写串口指令的格式,我们的程序流程细化为:在执行EE命令前,将串口地址0x3F8存入寄存器DX,将字符存入寄存器AL。

准备源操作数

由out指令可见,在运行指令之前需要将字符A存储到寄存器AL中。x86提供了数据复制指令mov,用于将数据从原操作数复制到目的操作数。原操作数是一个8位立即数,目的操作数是r8,表示一个8位寄存器。

操作码 指令 描述
B0+rb mov r8,imm8 将一个8位立即数复制到一个8位寄存器

指令编码为(B0+rb)ib。根据x86手册,其中rb表示使用操作码的低三位编码目的操作数,即将目的操作寄存器r8的编码嵌入操作吗的低三位。寄存器AL对应的编码为0,因此B0+rb最终编码为B0。

指令编码中的ib对应原操作数,其中i表示立即数,b表示立即数的宽度是一个字节。所以,ib表示跟在操作码之后的是一个8位立即数,和字符对应的ASCII码组合最终(B0+rb)ib的编码分别为:B068 B065 B06C B06C B06F B077 B06F B072 B06C B064。

准备目的操作数

我们需要将串口地址写到寄存器DX中,实质是将一个16位立即数复制到一个16位寄存器, 这显然还是一个数据复制操作

操作码 指令 描述
B8+rw mov r16,imm16 将一个16位立即数复制到一个16位寄存器

这个格式mov指令也接受两个操作数,只不过是16位的。指令编码中的rw表示使用操作码的低三位编码目的操作数,即将目的操作寄存器r16的编码嵌入操作码的低三位。根据x86手册,寄存器DX对应的编码为2,因此B8+rw编码为BA。

指令编码的iw中的i表示立即数,w表示立即数的宽度是一个字,即两个字节。所以iw表示跟在操作码之后的是一个16位立即数,这里即串口地址。不过x86处理器使用小端模式,所以最终(B8+rw)iw的编码为BAF803。

跳转指令

我们的程序循环向串口输出字符串helloworld,在向串口输出后,需要跳转到程序开始的位置,因此需要一个跳转指令jmp,格式如下。

操作码 指令 描述
EB cb jmp rel8 跳转到指令指针+rel8的位置

jmp指令后接一个rel8。rel是relative的缩写,表示相对的意思,8代表8位,因此可以跳转到相对这条指令-128~127的范围。在指令编码中操作码EB之后“cb”就是这个8位的相对偏移。

如果我们想让指令指针指向程序开头,即B0所在的内存地址,那么jmp需要向后跳转35个字节。因为是向后跳转,所以是-35,又因为计算机中使用的是补码,所以我们需要转换一下,根据原码转补码的规则-35的原码是10100011,补码就为11011101,使用16进制表示,即DD。

至此,我们就完成了这段程序的机器语言编码:

ba f8 03
b0 68
ee
b0 65
ee
b0 6c
ee
b0 6c
ee
b0 6f
ee
b0 77
ee
b0 6f
ee
b0 72
ee
b0 6c
ee
b0 64
ee
eb dd

创建程序文件

我们使用vim以二进制模式打开一个文件,vim -b hello_world.bin。按i进入插入模式,然后输入我们的代码

。输入完成后,按下ESC返回标准模式。在标准模式下按下“:”键,进入命令行模式。在“:”的后面输入将16进制转为二进制命令:

:%! xxd -p -r

"%"表示整个文件内容,”%!“一起使用表示将整个文件内容作为后面xxd的输入,然后使用xxd从16进制转为二进制的输出替换整个文件内容。-p 表示不需要任何格式,-r意为反过来。最后输入:“wq”保存退出

使用kvmtool运行程序

sudo kvmtool/lkvm run -c 1 -k hello_world.bin

机器语言编写helloworld的更多相关文章

  1. Hadoop学习笔记(5) ——编写HelloWorld(2)

    Hadoop学习笔记(5) ——编写HelloWorld(2) 前面我们写了一个Hadoop程序,并让它跑起来了.但想想不对啊,Hadoop不是有两块功能么,DFS和MapReduce.没错,上一节我 ...

  2. 开天辟地-用visualstudio2010编写helloworld

    安装好visual之后,创建新项目 向源文件添加helloworld.cpp 编写helloworld代码,编译运行即可 在运行时候出现一个错误,错误和解决方法如下:

  3. 运维开发笔记整理-使用Django编写helloworld

    运维开发笔记整理-使用Django编写helloworld 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.创建Django项目 1>.创建Django项目 djang ...

  4. X86平台下用汇编写"HelloWorld"

    首先需要安装一个汇编器,我用的是Nasm,这个汇编器在Linux下安装还是很简单的. Nasm下载地址http://www.nasm.us/pub/nasm/releasebuilds/ 在下载之后对 ...

  5. Android环境搭建和编写helloworld

    一.配置jdk环境(学过java的请无视) 1.安装jdk jdk下载地址:http://www.oracle.com/technetwork/cn/java/javase/downloads/jdk ...

  6. Hadoop教程之编写HelloWorld(2)

    前面我们写了一个Hadoop程序,并让它跑起来了.但想想不对啊,Hadoop不是有两块功能么,DFS和MapReduce.没错,上一节我们写了一个MapReduce的HelloWorld程序,那这一节 ...

  7. 用记事本编写helloworld文件但是javac时报错

    刚开始编写第一个java文件时遇到的错误: javac HelloWorld.java HelloWorld.java:1: 错误: 写入HelloWorld时出错: HelloWorld.class ...

  8. 全志A33 lichee 搭建Qt App开发环境编写helloworld

    开发平台 * 芯灵思SinlinxA33开发板 淘宝店铺: https://sinlinx.taobao.com/ 嵌入式linux 开发板交流 QQ:641395230 Step 1 在虚拟机(Ce ...

  9. Linux安装jdk,编写helloworld程序

    今天学习了Linux安装jdk,做个笔记记录一下. 第一步,确定Linux是32位的还是64位的,然后到oracle官网上下载对应版本的jdk,一般下载.tar.gz文件.查看Linux的版本的命令是 ...

  10. 【SpringBoot】02.编写HelloWorld

    1.编写一个返回HelloWorld的Controller @Controller public class HelloWorld { @ResponseBody @RequestMapping(&q ...

随机推荐

  1. 问题处理:java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp

    问题说明 今天跑spring boot项目,在查看列表数据时后台抛异常了,一看是这玩意: 问题原因 "0000-00-00 00:00:00"在mysql中是作为一个特殊值存在的但 ...

  2. jsp中无法识别EL表达式问题

    今天在开发系统时需要在JSP中遍历List<javabean>,其中用到了EL表达式:${item.value} 页面死活不出数据,只显示表达式本身:${item.value}. 页面代码 ...

  3. win32 - ReadDirectoryChangesW的使用

    任务:创建一个进程,并在进程内创建一个文本,再创建另一个进程来监控第一个进程内的文本变化 //Process 1 #include <windows.h> #include <ios ...

  4. Basic语言开发笔记:Basic语言介绍、环境搭建、基本语法示例与程序实例

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  5. 案例分享:Qt出版社书籍配套U盘资源播放器软件定制(脚本关联播放器与资源文件,播放器,兼容win7,win10和mac)

    红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术.树莓派.三维.OpenCV.OpenGL.ffmpeg.OSG.单片机.软硬结合等等)持续更新中-(点击传送门) 合作案例专栏:案例分享(体 ...

  6. chrome浏览器配置自定义搜索引擎

    chrome谷歌浏览器配置自定义搜索引擎 放弃百度搜索已经酝酿许久,现在搜索结果简直不忍直视.如果你想放弃使用百度搜索,并转向其他搜索引擎,头条搜索可能是一个不错的选择. 使用以下方式可以丝滑的使用其 ...

  7. springboot多线程TaskExecutor的使用,以及使用@Async实现异步调用

    目录 @Async实现异步调用 pom.xml 启动类 定义controller 定义接口 实现类 将isDone换程CountDownLatch来判断线程是否执行完实例化CountDownLatch ...

  8. 【Azure 微服务】Azure Service Fabric 因证书问题而使得 Node 一直处于 Down 状态

    问题描述 Service Fabric 集群更新证书后,重启Node后就变为Down的状态,反复 Restart 结果反复Down 问题分析 根据Service Fabric的文档表示,修改证书时一定 ...

  9. Spring Boot+Thymeleaf+MyBatis--推荐一个后端练手极佳的商城项目

    项目整体架构 newbee-mall ├── src/main/java └── ltd.newbee.mall ├── common // 存放相关的常量配置及枚举类 ├── config // 存 ...

  10. Netty笔记(2) - 基本实现与异步模型

    示例内容: 服务端监听6668端口 , 客户端连接 并发送信息给服务端 ,服务端收到信息打印 并返回信息给客户端 服务端代码: public class NettyServer { public st ...