DRAM芯片存储单元
在汇编语言课程作业PTA 上有这样一道题:DRAM芯片内部采用双译码结构,CPU送出的地址被分时送行译码器和列译码器。CPU送出的32位地址A的低16位和高16位分别送入行译码器和列译码器,编写程序输出行选择线和列选择线的序号。
输入样例:
在这里给出一组输入。例如:
263424
输出样例:
在这里给出相应的输出。例如:
1280 4
说实话,我第一次连题目都没有看懂,所以我们要补充一下DRAM芯片存储单元的知识。
在DRAM存储器中:n位地址会被拆成行地址和列地址,分别送给行地址译码器和列地址译码器。
这样的话,每个译码器只需要处理n/2位地址信息。
原本译码器需要处理20位地址信息,对应220=1M根选通线。那么现在将20位地址信息分别拆分,一半行地址,一半列地址,那么每个译码器的选通线就是210=1K根选通线,1024根选通线在工程上很容易实现。
我们可以看到就是将前16位放到一个寄存器中,再将后16位放到另一个寄存器中,进行输出。
; 声明外部函数printf,用于输出格式化的字符串。
extern printf
; 声明外部函数scanf,用于读取格式化的输入。
extern scanf
; 定义数据段,用于存储程序中的静态数据。
section .data
; 定义一个字节数组infrm,包含用于scanf的格式化字符串"%u",用于读取无符号整数。
infrm db "%u"
; 定义一个字节数组outfrm,包含用于printf的格式化字符串"%u %u",后面跟着换行符和字符串结束符。
outfrm db "%u %u", 10, 0
; 定义一个双字(dword)变量x,初始化为0。
x dd 0
; 定义一个双字(dword)变量y,初始化为65536(即2^16)。
y dd 65536
; 定义代码段,这里包含了程序的执行指令。
section .code
; 声明全局入口点main,这是程序的起始执行点。
global main
main:
; 将变量x的地址压入栈中,作为scanf读取数据的存储位置。
push x
; 将infrm的地址压入栈中,作为scanf的格式化字符串。
push infrm
; 调用scanf函数,读取一个无符号整数并存放到变量x中。
call scanf
; 调整栈指针,移除scanf压入的参数。
add esp, 8
; 将变量x的值加载到eax寄存器中。
mov eax, [x]
; 将eax寄存器中的值复制到edx寄存器中,用于后续的高位处理。
mov edx, eax
; 将edx寄存器中的值右移16位,获取x的高16位。
shr edx, 16
; 将eax寄存器中的值左移16位,再右移16位,以清除低16位,保留高16位。
shl eax, 16
shr eax, 16
; 下面的三行注释掉的代码是另一种计算x的高16位和低16位的方法,但在此处并未使用。
;mov eax, [x]
;mov edx, 0
;div dword [y]
; 将edx寄存器中的值(高16位)压入栈中。
push edx
; 将eax寄存器中的值(低16位)压入栈中。
push eax
; 将outfrm的地址压入栈中,作为printf的格式化字符串。
push outfrm
; 调用printf函数,输出两个无符号整数(x的高16位和低16位),后面跟一个换行符。
call printf
; 调整栈指针,移除printf压入的参数。
add esp, 12
; 将eax寄存器设置为0,表示程序正常退出。
mov eax, 0
; 从main函数返回,结束程序执行。
ret