Loading...

Question?

一. Assemble

asm: BLITZ汇编程序/汇编机

1
asm Hello.s

结果:创建一个Hello.o的文件

  • asm:命令行工具名称,通常是一个汇编器
  • .s: 汇编语言源文件
  • .o:二进制格式对象文件,包含了编译后但未链接的代码
  • 编译:将源代码(通常是高级编程语言写的)转化为机器语言或中间代码的过程,输出通常是对象文件
  • 链接:将一个或多个对象文件以及可能的其他库文件组合在一起,生成一个可执行文件或库文件的过程,输出是一个可执行文件

lddd:BLITZ链接器

1
lddd Hello.o –o Hello

告诉链接器 “lddd” 将 “Hello.o” 对象文件链接成一个名为 “Hello” 的可执行文件,链接器生成的可执行文件默认命名为 “a.out”,但是通过使用 “–o Hello” 选项,可以指定输出的可执行文件的名称为 “Hello”


三. blitz

1
blitz -g Hello
  • blitz:BLITZ 虚拟机(或称为模拟器)的命令名.BLITZ 虚拟机用于模拟一个计算机系统,让用户可以在其上运行特定的程序
  • g:这是一个选项,代表“auto-go”。这意味着当该指令执行后,程序 Hello 会立即开始运行,不需要额外的命令或操作
  • Hello:BLITZ 虚拟机上执行的程序的名称,是一个可执行文件(bin的猜测🤨)
  • 提示符:在出现的提示符“>”后,你可以输入命令,例如“quit”来退出模拟器。简写方式是输入“q”
  • 退出时的统计:当你退出模拟器后,它会显示一些统计数据,如磁盘读取次数、磁盘写入次数、执行的指令数量、休眠时间和总经过的时间

四. kpl

1
kpl HelloWorld
  • kpl:kpl 是一个命令行工具,用于处理 KPL 语言的源代码(也就是.c和.h文件).
  • 输出文件: HelloWorld.s (bin的猜测🤨)

五. make

1
make
  • make 是一个构建自动化工具,用于自动编译、链接和构建项目。它根据用户定义的规则(通常在名为 makefile 或 Makefile 的文件中)来决定如何构建项目.

六.输入blitz xxx后可以使用的指令

  • uit (q):当您想要退出模拟器时使用。
  • help (h):当您不确定可以使用哪些命令或需要查看命令的简短描述时使用。
  • go (g):当您想让程序继续执行,直到遇到下一个停止点(例如“debug”语句)时使用。
  • step (s):当您希望逐条执行机器语言指令,观察程序的具体行为或找出错误时使用。
  • t:当您希望一次执行一个高级 KPL 语言语句时使用。
  • reset:reset命令重新读取可执行文件并完全复位CPU。这个命令在调试期间很有用。每当您希望重新执行一个程序(而不重新编译任何东西),您可以总是退出模拟器,然后重新启动它。reset命令做同样的事情,但更快
  • info (i):当您想查看虚拟 CPU 的当前状态,包括所有寄存器的值时使用。
  • stack (st):当您想查看执行堆栈,特别是当前的函数调用序列和它们的状态时使用。
  • frame (fr):当您想查看当前活动堆栈帧的详细信息,如局部变量的值时使用。
  • up:当您在堆栈中向上移动,即查看之前的堆栈帧或函数调用时使用。
  • down:当您在堆栈中向下移动,即查看后续的堆栈帧或函数调用时使用。

七. Poject2:System.c

  • MemoryEqual:比较两块内存的内容是否相同。如果两块内存的内容相同,则返回 true,否则返回 false
  • StrEqual:检查两个字符串是否有相同的大小并包含相同的字符。
  • StrCopy:将字符串 s2 的字符复制到字符串 s1。如果两个字符串的大小不同,则复制它们的最小大小。
  • StrCmp:比较两个字符串。返回 -1(如果 s1 < s2)、0(如果 s1 = s2)或 +1(如果 s1 > s2)。
  • Min:返回两个整数中的较小值。
  • Max:返回两个整数中的较大值。
  • printIntVar:打印一个整数变量的名称和值。
  • printHexVar:打印一个整数变量的名称和十六进制值。
  • printBoolVar:打印一个布尔变量的名称和值。
  • printCharVar:打印一个字符变量的名称和值。
  • printPtr:打印一个指针变量的名称和值。
  • nl:打印一个新行。
  • printNullTerminatedString:打印一个以 ‘\0’ 结尾的字符串。
  • KPLSystemInitialize:初始化内存区域。
  • KPLMemoryAlloc:从堆中分配内存。
  • KPLMemoryFree:释放堆内存。但是这个函数当前什么都不做。
  • KPLSystemError:在发生致命错误时调用此函数,打印一个消息并终止程序。
  • KPLIsKindOf:确定一个对象是否是给定类型或其超类/超接口的实例。
  • KPLUncaughtThrow:当一个错误被抛出但未被捕获时,运行时系统会调用此函数。
  • printCatchStack:打印所有在 CATCH_STACK 上的 CATCH_RECORD

八. Project2:Thread.c

  1. InitializeScheduler:

    • 初始化线程调度器。
    • 设置当前执行的程序为 “main-thread”。
    • 创建并初始化两个线程:mainThreadidleThread
    • 设置 currentThreadmainThread
    • 使得中断为可用状态。
  2. IdleFunction:

    • 空闲线程的函数。
    • 如果没有其他线程可运行,它会使 CPU 进入等待状态,直到下一个中断到达。
    • 否则,它会释放CPU,让其他线程执行。
  3. Run:

    • 开始执行指定的 nextThread 线程。
    • 当前线程会被挂起。
    • 该函数只从 “Thread.Yield” 和 “Thread.Sleep” 被调用。
  4. PrintReadyList:

    • 打印当前的就绪线程列表。
  5. ThreadStartMain:

    • 每个线程首先执行的函数。
    • 它调用线程的 “main” 函数。
    • 如果 “main” 函数返回,该函数将终止该线程。
  6. ThreadFinish:

    • 一个线程最后执行的函数。
    • 它会清理并回收线程对象。
  7. FatalError:

    • 在遇到致命错误时调用,打印错误消息并中止执行。
  8. SetInterruptsTo:

    • 设置中断状态(禁用或启用)并返回先前的中断状态。
  9. TimerInterruptHandler:

    • 当定时器中断发生时调用的处理函数。
    • 它会让当前线程放弃CPU,允许其他线程执行。
  10. ThreadPrint:

    • 打印线程的详细信息,包括其名称、状态和地址。
  11. Thread behavior:

    • 定义了线程的行为和方法。

    • Init:

      • 初始化线程对象,但不安排其执行。
    • Fork:

      • 安排此线程执行。
    • Yield:

      • 当前线程可以通过执行此方法来放弃处理器。
    • Sleep:

      • 使当前线程进入阻塞状态并切换到执行另一个线程。
    • CheckOverflow:

      • 检查线程是否溢出其预分配的栈空间。
    • Print:

      • 打印此线程对象的详细信息。

九. Project2:Switch.s

  1. ThreadStartUp 函数:

    • 作用:这是每个线程开始执行的地方。每当一个新线程被创建并开始执行时,它首先运行这个函数。
    • 详细描述
      • Fork 函数会将这个函数的起始地址放入线程对象中,因此 Switch 将“返回”到这个地址,从而跳转到这个函数的第一个指令。
      • 这个函数初始化高级 KPL 代码所需的所有寄存器(即 r12 和 r14)。
      • 然后调用 KPL 函数 ThreadStartMainThreadStartMain 将调用线程的“main”函数。重要的是,ThreadStartMain 永远不会返回。
      • 如果某种原因程序到达 ThreadHang 标签,它会进入一个无限循环,因为这表示出现了错误。
  2. Switch 函数:

    • 作用:它是一个上下文切换函数,用于在两个线程之间切换执行状态。
    • 详细描述
      • 这个函数接收两个线程对象的指针。
      • 每个线程对象都包含一个可以存储机器状态的地方,这包括 r2-r14 寄存器以及堆栈顶部(r15)。
      • 这个函数首先保存 prevThread 的当前状态,然后从 nextThread 加载状态。
      • 一旦完成这个操作,函数返回,但由于线程已经切换,所以它返回到了不同的调用。

十. Project2:List.c

  1. AddToFront:

    • 作用:在链表的前端添加一个元素。
    • 描述:如果链表为空,则新元素成为链表的第一个和最后一个元素。否则,新元素将被插入到链表的前端。
  2. AddToEnd:

    • 作用:在链表的尾部添加一个元素。
    • 描述:如果链表为空,则新元素成为链表的第一个和最后一个元素。否则,新元素将被追加到链表的尾部。
  3. Remove:

    • 作用:从链表的前端移除一个元素并返回它。
    • 描述:如果链表为空,则返回 null。如果链表只有一个元素,则重置 firstlast 为 null。否则,更新 first 指向下一个元素。
  4. IsEmpty:

    • 作用:检查链表是否为空。
    • 描述:如果 first 存在,则链表不为空;否则,链表为空。
  5. ApplyToEach:

    • 作用:对链表中的每个元素应用一个函数。
    • 描述:这个方法遍历链表并对每个元素调用给定的函数。
  6. SortedInsert:

    • 作用:按照键值将元素插入到有序链表中的适当位置。
    • 描述:此方法假定链表已按键值排序。它将元素插入到适当的位置,确保链表仍然有序。
  7. SortedRemove:

    • 作用:从链表的前端移除一个元素并返回它。此外,它还返回元素的键值。
    • 描述:与 Remove 方法类似,但此方法还会返回已删除元素的键值。

十一. Project2:Main.c

  1. main:

    • 作用:主函数,从这里开始执行代码。
    • 描述:这个函数首先打印一条消息,然后初始化调度器。之后,它调用 SimpleThreadExample 函数(也可以选择其他的函数,但其他的调用被注释掉了)。最后,它调用 ThreadFinish 结束线程。
  2. SimpleThreadExampleSimpleThreadFunction:

    • 作用:这两个函数用于展示线程的基础用法。
    • 描述:创建一个新线程 aThread,并使用 Fork 方法使其执行 SimpleThreadFunction。主线程和新创建的线程都会调用 SimpleThreadFunction,但会传递不同的参数。这两个线程将交替执行,并在每次迭代后打印它们的名称。
  3. MoreThreadExamplesfoo:

    • 作用:演示如何创建和使用多个线程。
    • 描述:创建6个线程,每个线程都调用 foo 函数并传递一个不同的整数参数。这些线程将并发运行,并频繁地进行线程切换。
  4. TestMutexLockTester:

    • 作用:演示如何使用互斥锁(Mutex)来实现临界区和互斥。
    • 描述:创建7个线程,每个线程都试图在临界区内访问和修改一个共享整数。使用互斥锁确保每次只有一个线程可以访问临界区。
  5. ProducerConsumer, Producer, Consumer, 和 PrintBuffer:

    • 作用:实现生产者-消费者问题。
    • 描述:创建多个生产者和消费者线程。生产者在有限的缓冲区中放入字符,而消费者从中取出字符。这个示例演示了如何同步生产者和消费者的行为,确保当缓冲区满时生产者会等待,当缓冲区为空时消费者会等待。
  6. DiningPhilosophersPhilosphizeAndEat:

    • 作用:实现餐桌哲学家问题。
    • 描述:每个哲学家要么思考要么吃。在吃之前,他必须拿起两个叉子。吃完后,他放下叉子。由于叉子是共享的,所以访问它们需要同步。这个示例展示了如何使用一个监视器 (ForkMonitor) 来同步哲学家的行为。
  7. ForkMonitor 类:

    • 作用:为餐桌哲学家问题提供同步机制。
    • 描述:这个类的方法允许哲学家在他们需要时拾起和放下叉子。它还提供了一个方法来打印所有哲学家的状态。

十二. Project2:Synch.c

  1. Semaphore (信号量):

    • Init(initialCount): 初始化一个信号量,并设置其初始计数值为 initialCount。如果该值小于 0,则触发一个致命错误。
    • Up(): 增加信号量的计数值。如果有任何线程在等待,唤醒一个线程。这个操作永远快速执行并且不会挂起线程。
    • Down(): 减少信号量的计数值。如果计数值将变为负数,则等待其他线程首先执行 Up()。概念上,计数值永远不会变为负数。
  2. Mutex (互斥锁):

    • Init(): 初始化互斥锁。此方法未实现。
    • Lock(): 如果互斥锁是空闲的,就获取它,否则等待互斥锁变为空闲然后获取它。此方法未实现。
    • Unlock(): 释放互斥锁。如果其他线程在等待,唤醒最老的线程并给予它锁。此方法未实现。
    • IsHeldByCurrentThread(): 如果当前线程持有互斥锁,则返回 TRUE。此方法未实现。
  3. Condition (条件变量):

    • Init(): 初始化条件变量。
    • Wait(mutex): 假定互斥锁已被锁定。此方法会解锁它,并休眠等待此条件上的信号。当信号被接收时,此方法会重新唤醒,重新锁定互斥锁,并返回。
    • Signal(mutex): 如果有线程在这个条件上等待,此方法会唤醒最老的线程并安排它运行。但是,由于当前线程持有互斥锁并且从未解锁,新唤醒的线程将被迫等待,直到它可以重新获得互斥锁并继续执行。
    • Broadcast(mutex): 这个方法类似于 Signal(),但它会唤醒等待此条件的所有线程,而不仅仅是下一个线程。