2020春 lec5 课后习题讨论
匿名2023/07/31 19:50:14提问
    lecture5student
341

随机抽取部分同学题解。

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
    }
}
```

回答(1
    推荐问答
      Simple Empty
      暂无数据