LOU746866153 L5 2020-02-20 11:12:47 lab0:Coding!
965 0

“操作系统实验-基于uCore OS(厦门大学)”实验报告

lab0:Coding!

#lab0:Coding!

1:了解汇编

实验内容:

Try below command

$cd related_info/lab0
$gcc -S -m32 lab0_ex1.c
copy

Then you will get lab_ex1.S.Try to understand the content & relationg of C file and S file.

实验结果:

输入命令

 cd ~/ucore_lab/related_info/lab0
 gcc -S -m32 lab0_ex1.c 
copy

(注:题目所示未给出完整路径,应填补完整路径,根据提示缺省目录为/home/shiyanlou/ucore_lab )

同时注意到实验楼的源码位置是/home/shiyanlou/ucore_lab,但是在虚拟机里源码位置在/home/moocos/下。又已知/home/username/ 表示用户目录,实验楼平台上的默认用户目录是shiyanlou,虚拟机上的默认用户目录是moocos。 所以在虚拟机的输入命令为 cd ~/ucore_lab/related_info/lab0 再输入gcc -S -m32 lab0_ex1.c ,此时在文件系统中 ~/ucore_lab/related_info/lab0目录下得到lab0_ex1.s文件。

(注:注意命令的大小字母区分 gcc -s -m32 lab0_ex1.c 得到的是a.out文件)

gcc表示使用了GCC扩展内联汇编。

-S表示只激活预处理和编译,把文件编译为汇编代码。

-m32指生成32位机器的汇编代码。 图片描述

lab0_ex1.c文件:

int count=1;
int value=1;
int buf[10];
void main()            
{                
   asm(    
        "cld \n\t"
        "rep \n\t"                         
        "stosl"
    :
    : "c" (count), "a" (value) , "D" (buf[0])
    :
      );
}
copy

asm关键字用于调用内联汇编程序,可在C或C++语句合法出现。如果有多行汇编,则每一行都要加上“\n\t”。其中“\n”是换行符,“\t”是tab符,在每条指令的结束加这两个符号,是为了让gcc把内联汇编代码翻译成一般的汇编代码时能够保证换行和留有一定的空格。

cld:将标志寄存器flag的方向标志位df清零,在字符串操作中使变址寄存器si或di的地址指针自动增加,字符串处理由前往后。

rep:在cx不等于0的情况下,对字符串执行重复操作。

stosl:相当于将EAX中的值保存到ES:EDI指向的地址中。 冒号后的语句指明输入,输出和被改变的寄存器。其中"c"(count)表明把count的值放入cx寄存器中,"a"(value)表明把value的值放入EAX寄存器中,"D"(buf[0])表明把buf[0]的值放进edi寄存器中。

所以该代码段功能是向buf中写上count个value值。

lab0_ex1.s文件:

.file    "lab0_ex1.c"
    .globl    count
    .data
    .align 4
    .type    count, @object
    .size    count, 4
count:
    .long    1
    .globl    value
    .align 4
    .type    value, @object
    .size    value, 4
value:
    .long    1
    .comm    buf,40,32
    .text
    .globl    main
    .type    main, @function
main:
.LFB0:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    pushl    %edi
    pushl    %ebx
    .cfi_offset 7, -12
    .cfi_offset 3, -16
    movl    count, %edx
    movl    value, %eax
    movl    buf, %ebx
    movl    %edx, %ecx
    movl    %ebx, %edi
#APP

6 "lab0_ex1.c" 1

cld 
rep 
stosl

0 "" 2

#NO_APP
    popl    %ebx
    .cfi_restore 3
    popl    %edi
    .cfi_restore 7
    popl    %ebp
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE0:
    .size    main, .-main
    .ident    "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits
copy

.s文件是根据命令由.c文件按照32位机器汇编而成。

2:用gdb调试

实验内容:

Try below command

$cd related_info/lab0
$gcc -g -m32 lab0_ex2.c
copy

Then you will get a.out. Try to use gdb to debug lab0_ex2.

实验结果:

输入命令

gcc -g -m32 lab0_ex2.c  
copy

-g为编译选项,编译源文件,生成a.out.文件。

输入运行程序的命令

$ gcc -o lab0_ex2 -g lab0_ex2.c         

$ ./lab0_ex2  
copy

程序运行结果为显示“Hello ,world!” 图片描述

输入命令加载lab0_ex2可执行文件,执行装入的lab_ex2

gdb lab0_ex2
run
copy

图片描述

输入命令查看程序出错的地方

where
copy

错误为没有堆栈 no stack

输入命令查看调用gets函数附近的代码。

list
copy

图片描述

输入命令第7行处设置断点并执行单步命令next

break 7
next
copy

发现程序无法运行 图片描述

输入print命令查看int的值,发现问题在于试图使用类型名作为一个表达式。

print int
copy

3:掌握指针和类型转换相关的C编程

实验内容:

对于如下的代码段

...
#define STS_CG32        0xC            // 32-bit Call Gate
#define STS_IG32        0xE            // 32-bit Interrupt Gate

#define SETGATE(gate, istrap, sel, off, dpl) {            \
    (gate).gd_off_15_0 = (uint32_t)(off) & 0xffff;        \
    (gate).gd_ss = (sel);                                \
    (gate).gd_args = 0;                                    \
    (gate).gd_rsv1 = 0;                                    \
    (gate).gd_type = (istrap) ? STS_TG32 : STS_IG32;    \
    (gate).gd_s = 0;                                    \
    (gate).gd_dpl = (dpl);                                \
    (gate).gd_p = 1;                                    \
    (gate).gd_off_31_16 = (uint32_t)(off) >> 16;        \
}

 /* Gate descriptors for interrupts and traps */
 struct gatedesc {
    unsigned gd_off_15_0 : 16;        // low 16 bits of offset in segment
    unsigned gd_ss : 16;            // segment selector
    unsigned gd_args : 5;            // # args, 0 for interrupt/trap gates
    unsigned gd_rsv1 : 3;            // reserved(should be zero I guess)
    unsigned gd_type : 4;            // type(STS_{TG,IG32,TG32})
    unsigned gd_s : 1;                // must be 0 (system)
    unsigned gd_dpl : 2;            // descriptor(meaning new) privilege level
    unsigned gd_p : 1;                // Present
    unsigned gd_off_31_16 : 16;        // high bits of offset in segment
 };

... 
copy

如果在其他代码段中有如下语句,

unsigned intr;
intr=8;
SETGATE(intr, 0,1,2,3);
copy

请问执行上述指令后,intr的值是多少?

具体方法:Try below command

$cd related_info/lab0
gcc -g -m32 lab0_ex3.c 2>&1|tee make.log
copy

If you get gcc's error, try to read make.log and fix the bugs. If gcc successed, then you will get a.out. Try to answer below question.

实验结果:

输入命令

gcc -g -m32 lab0_ex3.c 2>&1|tee make.log
copy

2>&1是把错误输出和正常输出导到一起,然后通过tee写入log文件,同时在屏幕上继续输出 图片描述

发现错误在第48行,

printf("gintr is 0x%llx\n",gintr);
copy

%llx表示long long unsigned int (注:文件存放的路径是/home/ucore_lab/related_info/lab0) 打开lab0_ex3.c,发现在第39行中,gintr的类型为struct gatedesc,很明显类型不一致。

struct gatedesc gintr;
copy

按照错误提示,把输出语句删除。

输入命令重新编译(在虚拟机里的文件似乎不太对,我直接在实验楼的在线环境尝试了)

$gcc -g -m32 lab0_ex3.c 2>&1|tee make.log
copy

生成a.out文件

运行a.out,得到结果 intr is 0x10002

$./a.out
copy

图片描述

4:掌握通用链表结构相关的C编程

实验内容:

用在related_info/lab0/list.h中定义的结构和函数来实现一个小应用程序完成一个基于此链表的数据对象的访问操作。可参考related_info/lab0/lab0_ex4.c

实验结果:

list.h文件

#ifndef __LIBS_LIST_H__
#define __LIBS_LIST_H__

#ifndef __ASSEMBLER__

#include <defs.h>

/* *

- Simple doubly linked list implementation.
  *
- Some of the internal functions ("__xxx") are useful when manipulating
- whole lists rather than single entries, as sometimes we already know
- the next/prev entries and we can generate better code by using them
- directly rather than using the generic single-entry routines.
- */

struct list_entry {
    struct list_entry *prev, *next;
};

typedef struct list_entry list_entry_t;

static inline void list_init(list_entry_t *elm) __attribute__((always_inline));
static inline void list_add(list_entry_t *listelm, list_entry_t *elm) __attribute__((always_inline));
static inline void list_add_before(list_entry_t *listelm, list_entry_t *elm) __attribute__((always_inline));
static inline void list_add_after(list_entry_t *listelm, list_entry_t *elm) __attribute__((always_inline));
static inline void list_del(list_entry_t *listelm) __attribute__((always_inline));
static inline void list_del_init(list_entry_t *listelm) __attribute__((always_inline));
static inline bool list_empty(list_entry_t *list) __attribute__((always_inline));
static inline list_entry_t *list_next(list_entry_t *listelm) __attribute__((always_inline));
static inline list_entry_t *list_prev(list_entry_t *listelm) __attribute__((always_inline));

static inline void __list_add(list_entry_t *elm, list_entry_t *prev, list_entry_t *next) __attribute__((always_inline));
static inline void __list_del(list_entry_t *prev, list_entry_t *next) __attribute__((always_inline));

/* *

- list_init - initialize a new entry
- @elm:        new entry to be initialized
- */
  static inline void
  list_init(list_entry_t *elm) {
   elm->prev = elm->next = elm;
  }

/* *

- list_add - add a new entry
- @listelm:    list head to add after
- @elm:        new entry to be added
  *
- Insert the new element @elm *after* the element @listelm which
- is already in the list.
- */
  static inline void
  list_add(list_entry_t *listelm, list_entry_t *elm) {
   list_add_after(listelm, elm);
  }

/* *

- list_add_before - add a new entry
- @listelm:    list head to add before
- @elm:        new entry to be added
  *
- Insert the new element @elm *before* the element @listelm which
- is already in the list.
- */
  static inline void
  list_add_before(list_entry_t *listelm, list_entry_t *elm) {
   __list_add(elm, listelm->prev, listelm);
  }

/* *

- list_add_after - add a new entry
- @listelm:    list head to add after
- @elm:        new entry to be added
  *
- Insert the new element @elm *after* the element @listelm which
- is already in the list.
- */
  static inline void
  list_add_after(list_entry_t *listelm, list_entry_t *elm) {
   __list_add(elm, listelm, listelm->next);
  }

/* *

- list_del - deletes entry from list
- @listelm:    the element to delete from the list
  *
- Note: list_empty() on @listelm does not return true after this, the entry is
- in an undefined state.
- */
  static inline void
  list_del(list_entry_t *listelm) {
   __list_del(listelm->prev, listelm->next);
  }

/* *

- list_del_init - deletes entry from list and reinitialize it.
- @listelm:    the element to delete from the list.
  *
- Note: list_empty() on @listelm returns true after this.
- */
  static inline void
  list_del_init(list_entry_t *listelm) {
   list_del(listelm);
   list_init(listelm);
  }

/* *

- list_empty - tests whether a list is empty
- @list:       the list to test.
- */
  static inline bool
  list_empty(list_entry_t *list) {
   return list->next == list;
  }

/* *

- list_next - get the next entry
- @listelm:    the list head
  **/
  static inline list_entry_t *
  list_next(list_entry_t *listelm) {
  return listelm->next;
  }

/* *

- list_prev - get the previous entry
- @listelm:    the list head
  **/
  static inline list_entry_t *
  list_prev(list_entry_t *listelm) {
  return listelm->prev;
  }

/* *

- Insert a new entry between two known consecutive entries.
  *
- This is only for internal list manipulation where we know
- the prev/next entries already!
- */
  static inline void
  __list_add(list_entry_t *elm, list_entry_t *prev, list_entry_t *next) {
   prev->next = next->prev = elm;
   elm->next = next;
   elm->prev = prev;
  }

/* *

- Delete a list entry by making the prev/next entries point to each other.
  *
- This is only for internal list manipulation where we know
- the prev/next entries already!
- */
  static inline void
  __list_del(list_entry_t *prev, list_entry_t *next) {
   prev->next = next;
   next->prev = prev;
  }

#endif /* !__ASSEMBLER__ */

#endif /* !__LIBS_LIST_H__ */
copy

该文件中包含的链表的初始化,节点的插入,删除等操作。

lab0_ex4.c文件:

#include <stdio.h>
#include <stdlib.h>
#include "list.h"

struct entry {

​```
list_entry_t node;
int num;
​```

};

int main() {
    struct entry head;
    list_entry_t* p = &head.node;
    list_init(p);
    head.num = 0;
    int i;
    for (i = 1; i != 10; i ++) {
        struct entry * e = (struct entry *)malloc(sizeof(struct entry));
        e->num = i;
        list_add(p, &(e->node));
        p = list_next(p);
    }
    //reverse list all node
    while ((p = list_prev(p)) != &head.node)
        printf("%d\n", ((struct entry *)p)->num);
    return 0;
}
copy

运行lab0_ex4.c

$ gcc -g -m32 lab0_ex4.c
copy

发现代码中出现错误 图片描述

在list.h文件中将<defs.h>改为“defs.h"

重新运行,生成a.out文件,运行a.out文件 图片描述

最新评论
暂无评论~