随机抽取部分同学题解。
Nature

Python
```python
import sys
from memory import *
# 判断是否为合法数据
def ifvalid(bitstring):
isvalid = bitstring >> 7
return_number = bitstring & 0b01111111
if isvalid == 1:
return True,return_number
else:
return False,return_number
# 读入要求访问的虚拟地址
virtual_address = int(sys.argv[1][2:],16)
print("virtual virtual_address is " + hex(virtual_address))
page_directory_base_registor = 0x220
base_index = 0x220 >> 5
pde_index_mask = 0b0111110000000000
pte_index_mask = 0b0000001111100000
offset_mask = 0b0000000000011111
pde_index = (virtual_address & pde_index_mask) >> 10
pte_index = (virtual_address & pte_index_mask) >> 5
offset = virtual_address & offset_mask
# mem[page_index][entry_index] 为已处理好的二维数组
first_level_number = mem[base_index][pde_index]
flag, pte_base = ifvalid(first_level_number)
# 说明不合法
if not flag:
print(" --> pde index : "+ str(hex(pde_index))+ " pde contents : (valid = 0 pfn = " + str(hex(pte_base))+")")
print(" --> Fault (page directory entry not valid)")
else:
print(" --> pde index : "+ str(hex(pde_index))+ " pde contents : (valid = 1 pfn = " + str(hex(pte_base))+")")
second_level_number = mem[pte_base][pte_index]
flag_2, ppn_base = ifvalid(second_level_number)
if not flag_2:
print(" --> pte index : "+ str(hex(pte_index))+ " pde contents : (valid = 0 pfn = " + str(hex(ppn_base))+")")
print(" --> Fault (page table entry not valid)")
else:
print(" --> pte index : "+ str(hex(pte_index))+ " pde contents : (valid = 1 pfn = " + str(hex(ppn_base))+")")
number = mem[ppn_base][offset]
print(" --> Translates to physical address : " + str(hex((ppn_base<<5)+offset)) + " --> value : " + str(hex(number))+")")
```
不是问题的问题:信任了题目数据,注意虚拟地址可能非法(有冗余)。具体可参考如下函数。
```python
def read_storage(page,offset):
if page<0 or page>int('7f',16):
return -1
if offset<0 or offset>31:
return -1
return storage[page][offset]
```
C++
```C++
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
uint16_t BASE_ADD = 0x220;
void vir_to_phy(uint16_t base_add, int* phy_mem, uint16_t vir_addr){
printf("Virtual Address %04x :\n", vir_addr);
uint8_t pde_shift = vir_addr >> 10;
uint8_t pte_shift = (vir_addr >> 5) % 32;
uint8_t pde_contents = phy_mem[base_add + pde_shift];
printf(" --> pde index: %02x, pte contents: (valid: %01d, pfn %02x) \n",
pde_shift, pde_contents >> 7 ,pde_contents % 128);
if(pde_contents >> 7 == 0){
printf(" --> Fault (page ditectory entry not valid) \n");
return;
}
else {
uint8_t pte_contents = phy_mem[(pde_contents % 128)*32 + pte_shift];
printf(" --> pte index: %02x, pte contents: (valid: %01d, pfn %02x) \n",
pte_shift, pte_contents >> 7 ,pte_contents % 128);
if(pte_contents >> 7 == 0){
printf(" --> Fault (page table entry not valid) \n");
return;
}
else{
uint16_t value_addr = (uint16_t)((pte_contents % 128) << 5) + vir_addr % 32;
int value = phy_mem[value_addr];
printf(" --> Translates to physical address %02x --> Value: %02x \n", value_addr, value);
}
}
}
int main(){
int phy_mem[4096];
int i = 0;
FILE *fp;
fp = fopen("phymem.txt", "r");
while(fscanf(fp, "%2x", &(phy_mem[i])) !=EOF) i++;
uint16_t vir_addrs[10] = {0x6c74, 0x6b22, 0x03df, 0x69dc, 0x317a, 0x4546, 0x2c03, 0x7fd7, 0x390e, 0x748b};
for(auto va: vir_addrs){
vir_to_phy(BASE_ADD, phy_mem, va);
}
return 0;
}
```
RUST
```rust
use std::fs;
fn main() {
let mut pde_index : u8;
let mut pte_index : u8;
let mut page_offset : u8;
let mut pde_content : u8;
let mut pde_valid : u8;
let mut pde_addr : u8;
let mut pte_content : u8;
let mut pte_valid : u8;
let mut pte_addr : u8;
let mut paddr : u16;
let mut value : u8;
// load memory information
let contents = fs::read_to_string("memory.txt")
.expect("Something went wrong reading the file");
let mut mem = Vec::new();
let split = contents.as_str().split("\n");
for s in split {
mem.push(s.split(" ").collect::<Vec<&str>>());
}
let vec : Vec<u16> = vec![0x6c74, 0x6b22, 0x03df, 0x69dc, 0x317a, 0x4546, 0x2c03, 0x7fd7, 0x390e, 0x748b];
for addr in vec.into_iter() {
print!("\nthe virtual addr is {:#x} \n ", addr);
//parse the virtual addr
pde_index = (addr >> 10) as u8;
pte_index = ((addr << 6) >> 11) as u8;
page_offset = (addr % 32) as u8;
//get pde
pde_content = parse_str(mem[0x11][2 + pde_index as usize]);
pde_valid = pde_content >> 7;
pde_addr = pde_content - (pde_valid << 7);
//get pte
pte_content = parse_str(mem[pde_addr as usize][2+ pte_index as usize]);
pte_valid = pte_content >> 7;
pte_addr = pte_content - (pte_valid << 7);
//get physical address and value stored in it
paddr = ((pte_addr as u16) << 5) + page_offset as u16;
value = parse_str(mem[(paddr >> 5) as usize][2 + (paddr % 32) as usize]);
print!("the pde index is : {:#x}, pde content is {:#x} (valid {}, pfn {:#x})\n ", pde_index, pde_content, pde_valid, pde_addr);
if pde_valid != 0 {
print!("the pte index is : {:#x}, content is {:#x} (valid {}, pfn {:#x}) \n ", pte_index, pte_content, pte_valid, pte_addr);
}else{
println!("Fault (page directory entry not valid)");
continue;
}
if pte_valid != 0 {
print!("the page offset is : {:#x}, the paddr is {:#x}, value is {:#x} \n ", page_offset, paddr, value);
}else{
println!("Fault (page directory entry not valid)");
continue;
}
}
}
// convert str to number, such as '1b' => 27_u8
fn parse_str(s : &str) -> u8 {
let mut res : u8 = 0;
for ch in s.bytes() {
res = (res << 4) + parse_char(ch);
}
res
}
// convert char to number
fn parse_char(ch : u8) -> u8 {
match ch {
b'0'=> 0,
b'1'=> 1,
b'2'=> 2,
b'3'=> 3,
b'4'=> 4,
b'5'=> 5,
b'6'=> 6,
b'7'=> 7,
b'8'=> 8,
b'9'=> 9,
b'a'=> 10,
b'b'=> 11,
b'c'=> 12,
b'd'=> 13,
b'e'=> 14,
b'f'=> 15,
_ => 0
}
}
```