0%

查看Python的浮点数如何在内存中存储

下面的探讨主要针对Python3,在Python2中不一定适用。

Python的浮点数实现原理:
CPython实现有一个PyFloatObject的结构体,用来构造Python的浮点数类型:

typedef struct {
PyObject_HEAD # 这个对象包含:引用计数+对象类型,占8+8=16字节
double ob_fval; # 这个是存储浮点数的地方,Python的浮点数就是C的double,双精度
} PyFloatObject;

所以Python的浮点数类型占24字节:
引用计数+对象类型+双精度浮点数 = 8+8+8 = 24字节
不过Python3的整数长度无限,所以占字节数不定

用Python代码验证浮点数:

代码:

阅读全文 »

课程设计2

题目见 汇编语言 第四版 作者王爽 p312

这篇文章是《汇编语言 第四版》的完结篇。

概述

1、vm虚拟机中安装win98se,以下称为win98

2、成功安装系统后,虚拟机添加一个新软盘(需要创建软盘映像.img文件)。

3、启动win98系统,将下文源码编译,然后执行程序(需要masm汇编器)。

4、关闭win98系统,在虚拟机中,设置软盘为启动盘。

5、启动虚拟机,我们自己写的程序就能执行了。

如果用两个硬盘,即添加新硬盘代替软盘,然后设新硬盘为启动盘后,启动失败(暂不管此问题)!

程序结构

软盘:第1扇区存放我们的引导程序,第2-3扇区存放主程序,实现4个功能。

硬盘1:是win98系统盘,第1扇区有mbr引导程序。

开机后,软盘为启动盘,加载我们自己的引导程序,执行引导程序,然后加载2-3扇区的主程序。

内存结构

阅读全文 »

中断例程装载程序源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
; 安装新的 7ch 中断例程,实现如下功能的子程序:
; 1) 清屏
; 2) 设置前景色
; 3) 设置背景色
; 4) 向上滚动一行

; 入口参数:
; ah=功能号:0清屏,1前景色,2背景色,3向上滚动一行
; 对于1、2号功能,用al传递颜色值,范围0~7的整数

assume cs:code
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset setscreent ; ds:si指向中断例程的代码

mov ax,0
mov es,ax
mov di,200h ; es:di指向中断例程装载位置
mov cx,offset setsrcend - offset setscreent ; 中断例程长度
cld
rep movsb ; 串传输

; 设置 7ch 号中断向量
mov ax,0
mov es,ax
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0

mov ax,4c00h
int 21h

; 中断处理程序开始
setscreent:
jmp short set ; 此指令占2字节
; 此dw数据开始地址为 0:200h入口地址+2 即0:202h
; sub1为数据标号,dw sub1相当于dw offset sub1
dw 200h+sub1-setscreent,200h+sub2-setscreent,200h+sub3-setscreent,200h+sub4-setscreent
set:
push bx
cmp ah,3 ; 判断功能号是否大于3
ja sret
mov bl,ah
mov bh,0
add bx,bx ; ah中的功能号*2=table表中的偏移
call word ptr cs:[bx+202h] ; 此中断执行时,cs=0
sret:
pop bx
iret

sub1: ; 清屏
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0 ; 显存的偶地址单元为字符
mov cx,2000
sub1s:
mov byte ptr es:[bx],' ' ; 空格填充屏幕
add bx,2
loop sub1s
pop es
pop cx
pop bx
ret

sub2: ; 设置字体颜色
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1 ; 显存的奇地址单元为属性
mov cx,2000
sub2s:
and byte ptr es:[bx],11111000b
or es:[bx],al
add bx,2
loop sub2s
pop es
pop cx
pop bx
ret

sub3: ; 设置背景色
push bx
push cx
push es
mov cl,4
shl al,cl
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub3s:
and byte ptr es:[bx],10001111b
or es:[bx],al
add bx,2
loop sub3s
pop es
pop cx
pop bx
ret

sub4: ; 向上滚动一行
push cx
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160 ; ds:si指向n+1行
mov di,0 ; es:di指向n行
cld
mov cx,24 ; 共复制24行
sub4s:
push cx
mov cx,160
rep movsb ; 一行复制完,si+=160,di+=160
pop cx
loop sub4s
mov cx,80
mov si,0
sub4s1:
mov byte ptr [160*24+si],' ' ; 最后一行清空
add si,2
loop sub4s1
pop ds
pop es
pop di
pop si
pop cx
ret
; 中断处理程序结束

setsrcend:
nop

code ends
end start
阅读全文 »

从 CMOS RAM 读取时间并显示到屏幕。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
; 显示CMOS中当前日期时间
assume cs:code
code segment
src:
db 9,8,7,4,2,0 ; 年月日时分秒的地址
dst:
db 'yy/mm/dd hh:mm:ss',0

start:
mov ax,cs
mov ds,ax
mov si,offset src
mov di,offset dst
mov cx,6
s:
mov dx,cx
mov al,[si]
out 70h,al ; 70h为地址端口
in al,71h ; 71h为数据端口
mov ah,al
mov cl,4
shr ah,cl ; 右移4位,ah为十进制的十位数
and al,00001111b ; al为十进制的个位数
add ah,30h
add al,30h ; 数值转字符形式
xor ah,al
xor al,ah
xor ah,al ; 交换ah al的值
mov [di],ax
add di,3
inc si
mov cx,dx
loop s

mov ax,0b800h
mov es,ax
mov di,0
mov si,offset dst
s1:
mov ch,0
mov cl,[si]
jcxz ok
mov ch,2 ; 绿色字
mov es:[di],cx
inc si
add di,2
jmp s1
ok:
mov ax,4c00h
int 21h
code ends
end start
阅读全文 »

1、编写安装7ch号中断例程,显示0结尾的字符串

中断例程装载程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
; 8086实模式 中断例程装载程序
; 中断号 7ch
; 装载位置 0:200h

assume cs:code
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset handler ; ds:si指向中断例程的代码

mov ax,0
mov es,ax
mov di,200h ; es:di指向中断例程装载位置
mov cx,offset handlerend - offset handler ; 中断例程长度
cld
rep movsb ; 串传输

; 设置 7ch 号中断向量
mov ax,0
mov es,ax
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0

mov ax,4c00h
int 21h

handler:
; 注意!下文中断例程装载程序,只提供 handler 标号的部分,即,
; 中断处理程序开始 与 中断处理程序结束 包裹的部分

; 中断处理程序开始
; 显示0结尾的字符串
; dh 行号、dl 列号、cl 颜色、ds:si指向字符串首
push si
push es
push di
push ax
push dx
push cx

mov ax,0b800h ; 显存开始位置
mov es,ax
mov al,dh
mov dh,160
mul dh ; ax=行号*160
mov dh,0
add dx,dx ; dx=列号*2
add ax,dx
mov di,ax ; di=行号*160+列号*2

s:
mov al,[si]
cmp al,0
je ok
mov ah,cl
mov es:[di],ax
add di,2
inc si
jmp s

ok:
pop cx
pop dx
pop ax
pop di
pop es
pop si
iret
; 中断处理程序结束
handlerend:
nop

code ends
end start
阅读全文 »

可以修改IP,或者同时修改CS与IP的指令统称为转移指令

因为CS:IP是指令寄存器,比较特殊,且CS无法用其他寄存器直接赋值,如:mov cs,ax。

所以需要jmp,call,ret,loop等指令来修改IP或同时修改CS与IP。

CS:IP的组合用来实现8086CPU的20位寻址(虽然8086的寄存器是16位的,但8086内部有20位地址加法器)。

另外,8086CPU是小端模式。内存高地址存放数据高位,内存低地址存放数据低位。

转移指令种类

8086转移指令种类:

  • 无条件转移指令(如 jmp)

  • 条件转移指令(如 jcxz)

  • 循环指令(如 loop)

  • 过程(如 call、ret、retf)

  • 中断

伪指令offset

offset 是伪指令,由汇编器识别并处理,用于取得标号的偏移地址。如:

阅读全文 »