代码之家  ›  专栏  ›  技术社区  ›  Tienus McVinger

使用程序集(16位引导加载程序)读取输入

  •  2
  • Tienus McVinger  · 技术社区  · 6 年前

    作为我的uni提供的一门课程,我按照教程编写了一个16位的汇编引导程序。 http://3zanders.co.uk/2017/10/13/writing-a-bootloader/ . 这部分(第一部分)是我到目前为止应该做的。它基本上什么都不做,只是把Hello World打印到屏幕上。

    现在,请记住,这是我在汇编中编写bootloader的唯一经验(这是我唯一的经验,句号)-我现在应该将它扩展到一个菜单,用户可以在其中选择三个选项之一,然后相应地输出一个字符串,因此:

    What is your favourite colour?
    Press 1 for red
    Press 2 for green
    Press 3 for blue
    
    [user input here]
    
    Your favourite colour is [whatever corresponding colour].
    

    我一直想弄清楚到底从哪里开始已经好几个小时了。我在汇编中找到了一些选择菜单的例子,但问题是这些例子中的代码与本教程“教给”我的东西毫无相似之处。我觉得我不得不从简单地将Hello World打印到屏幕,到制作一个根据用户输入打印不同输出的菜单。

    这是我目前拥有的:

    bits 16 ; tell NASM this is 16 bit code
    org 0x7c00 ; tell NASM to start outputting stuff at offset 0x7c00
    boot:
        mov si,startText ; point si register to startText label memory location
        mov ah,0x0e ; 0x0e means 'Write Character in TTY mode'
    .loop:
        lodsb
        cmp al,51
        je blue
        cmp al,50
        je green
        cmp al,49
        je red
    
        or al,al ; is al == 0 ?
        jz getInput  ; if (al == 0) jump to halt label
        int 0x10 ; runs BIOS interrupt 0x10 - Video Services
        jmp .loop
    getInput:
        mov ah,00h
        int 16h
    red:
        db "Your favourite colour is red",0
    green:
        db "Your favourite colour is green",0
    blue:
        db "Your favourite colour is blue",0
    halt:
        cli ; clear interrupt flag
        hlt ; halt execution
    startText:
        db "",13,10
        db "what is your favourite colour?",13,10
        db "Press one for red",13,10
        db "Press two for green",13,10
        db "Press three for blue",13,10
        db 13,10,0
    
    times 510 - ($-$$) db 0 ; pad remaining 510 bytes with zeroes
    dw 0xaa55 ; magic bootloader magic - marks this 512 byte sector bootable!
    

    编辑2: 我再次更新了上述代码,试图实现SEP和John告诉我的内容。我意识到这不是它应该是怎样的,他们告诉我的某些事情并没有实现,因为我还不知道该怎么做。

    我认为,现在的问题是,在显示初始的“惊吓标签”之后,它什么都不做。如果我按任何按钮都不会改变。如果有人能为我指明更正确的方向,我将不胜感激!

    enter image description here

    2 回复  |  直到 6 年前
        1
  •  2
  •   John Burger    6 年前

    1)您错过了一个@seproland_s积分。您的代码 .loop 加载每个单独的字符,如果是 不是 ==0 它把它打印出来并重复这个循环。这意味着你有责任 提供 这个 0 在你的数据中:

    db "",13,10
    

    应该是:

    db 13,10,0
    

    (注意 ”” 是一个空字符串-无需打印-因此是不必要的。)

    看到屏幕截图上的垂直线了吗?这实际上是计算机打印出以下操作码 mov 指令!垃圾输出是因为代码已停止打印数据,现在正在打印实际代码的字节。它将继续这样做,直到代码 -哪一个(幸运的?)刚好是下一个字节!以上 ,0 会阻止这一切。

    2)好的,那么当它(最终)加载 是吗?根据你的评论,它将跳到停止标签。当然,代码随后跳到 cli hlt 指令-计算机停止工作。它没有机会执行 mov ah,00h int 16h 你在下面添加的。

    您需要将这些行移到 halt 贴上标签-并给他们贴上自己的标签: getInput 或者什么的。然后改变 jz halt 以上 jz getInput 相反:你希望它得到输入,而不是停止!

    然后您需要添加代码以打印出结果。您已经知道如何打印字符串:您只需打印出以前的不同字符串—您将需要为这些字符串添加新的和不同的标签。别忘了决赛 每一次!

    Sep给了你我所描述的大部分;你还没有把它们放在一起。您需要在头脑中区分计算机将执行的代码与计算机将处理的数据。对PC来说,它们都是数字,它会很高兴地执行代码,然后在遇到数据时开始执行数据——至少,直到数据让它做了一些愚蠢的事情!

    [编辑] 3)看来我们需要回到第一原则。假装 是电脑,拿一张纸和一支笔,然后执行你提供的指令。从最上面开始:

    • 画一个盒子,贴上标签 si 并提出 startText 里面。那是第一次 压敏电阻 .
    • 画另一个盒子,贴上标签 ah 并提出 0x0e 里面。那是第二个 压敏电阻 .
    • 记下 回路 行-你以后需要它。
    • 这个 lodsb 说明有点复杂。它使用 要查看内存,请将该值加载到 al (你需要一个新的盒子),然后添加一个到 . 因为 持有 星条集 ,第一个字节位于 星条集 (the 13 记住, "" 为空)加载到 . 放 十三 在里面 和追加 +1 里面 .

      顺便说一下:花点时间想想你刚装了什么。它是要打印出的一系列字节中的第一个字节。所以很快你就需要调用“打印字符”程序了。

    • 现在你在比较 具有 51 -的ASCII值 3 就像九月建议的那样。(注意,你可以 '3' 而不是 五十一 使代码更容易理解。注意单引号(不是双引号)。

      嗯,这是怎么回事?你加载了一个字符要打印-现在你要检查它是否是数字3?这不是在处理答案吗?在你要求电脑得到答案之前?在打印出要求用户键入答案的字符串之前?

    您已经添加了建议使用的代码——但完全错误。在试图编写执行这些操作的代码之前,您需要后退一步,用高级语言写下您希望程序执行的操作。

    我建议您执行以下操作:

    1. 写出要求用户喜欢哪种颜色的字符串
    2. 从用户处获取输入
    3. 如果答案是三个预期答案之一,则写出结果。

      否则,写下“意外答案”,然后回到步骤2。

    4. 停顿
    5. 要打印的数据

    最重要的是,所有这些代码都需要按正确的顺序放在一起,中间没有数据。代码不仅必须存在,而且必须按照您希望计算机执行它们的顺序出现。

    你拥有的是:

    3.如果答案是三个预期答案之一,则写出结果。

    1.写出要求用户喜欢哪种颜色的字符串

    2.从用户那里获取输入

    5、数据

    4、停止

    5、更多的数据

        2
  •  1
  •   Sep Roland    6 年前

    这将为您指明正确的方向。

    hello: 
    db "What is your favourite colour?",13,10
    db "Press 1 for red"13,10
    db "Press 2 for green"13,10
    db "Press 3 for blue"13,10
    db "",13,10
    

    首先,通过正确地零结束此消息,而不省略逗号来更正此消息:

    hello: 
    db "What is your favourite colour?",13,10
    db "Press 1 for red",13,10
    db "Press 2 for green",13,10
    db "Press 3 for blue",13,10
    db 13,10,0
    

    要输入,可以使用键盘int 16h上的BIOS功能00h:

    mov ah, 00h
    int 16h
    

    如果用户按“1”,则 AL 寄存器将保存值49。
    如果用户按“2”,则 寄存器将保存值50。
    如果用户按“3”,则 寄存器将保存值51。

    现在,显示“您最喜欢的颜色是”的常见信息。在此操作过程中,必须注意不要意外地修改 . 使用保存 push ax pop ax 围绕这部分代码。

    然后测试通过读取键盘获得的值,以选择指针( SI )一个合适的信息。显示该消息(仅显示颜色的名称)。终于 halt .