NASM 模块将十六进制转换为字符串并打印出来。已组装但未按预期工作

2023-12-27

我正在尝试编写一个简单的汇编代码以将十六进制值输出到屏幕上。有两个文件print_screen.asm它正在与其他模块一起工作。我认为问题出在我尝试将十六进制转换为字符串时的逻辑中。我的代码是:

[org 0x7c00]

xor dx,dx
xor ax,ax
xor bx,bx

mov dx, 0x1fb6

call print_hex

jmp endi;

print_hex:
    pusha

    mov ax,0x0001
    and ax,dx
    add ah,48
    mov byte [HEX_OUT+5],ah

    mov ax,0x0010
    and ax,dx
    add ah,48
    mov byte [HEX_OUT + 4],ah

    mov ax,0x0100
    and ax,dx
    add ah,48
    mov byte [HEX_OUT + 3],ah

    mov ax,0x1000
    and ax,dx
    add ah,48
    mov byte [HEX_OUT + 2],ah

    mov bx,HEX_OUT
    call print_string

    popa
    ret

jmp endi

%include "print_string.asm"

endi:
;data
HEX_OUT: db '0x0000',0

SAMPLE: db 'a',0
times 510 - ($-$$) db  0
dw 0xaa55

print_screen.asm(与其他模块一起使用):

 print_string:
    pusha
    cld
    mov ah,0x0e

config: mov al,[bx]
    ;Comparing the strings
    cmp byte [bx],0x00  ;Comparing for null
    jne print
    je end

print:  int 0x10
    add bx,1
    jmp config

end:    popa
    ret

mov ax,0x0001
and ax,dx
add ah,48
mov byte [HEX_OUT+5],ah

在上面的代码片段中,您只保留了一位,而您需要保留 4 位。
您还做了补充AH当结果肯定是AL.
由于 ASCII 集的组织方式,您不能简单地添加 48 来转换为十六进制。 “9”(57)的编码和“A”(65)的编码之间存在差距。您的代码需要考虑到这一点!

对于最低有效的十六进制数字:

    mov ax, dx     ;Original number
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + 5], al

对于下一个十六进制数字,这将变成:

    mov ax, dx     ;Original number
    shr ax, 4
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + 4], al

对于下一个十六进制数字,这将变成:

    mov ax, dx     ;Original number
    shr ax, 8
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + 3], al

对于下一个十六进制数字,这将变成:

    mov ax, dx     ;Original number
    shr ax, 12
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + 2], al

这很快就变得比对我们有利的时间更长,所以使用loop会好很多。
下一个解决方案将从高端开始,但最终结果不会有什么不同。

    mov bx, 2      ;Position for most significant digit
.Next:
    ror dx, 4      ;Bring digit in lowest 4 bits
    mov al, dl     ;Copy number
    and al, 15     ;Keep 4 bits
    add al, '0'    ;Make text
    cmp al, '9'
    jbe .LessA     ;Already fine for '0' to '9'
    add al, 7      ;Bridge the gap to reach 'A' to 'F'
.LessA:
    mov [HEX_OUT + bx], al
    inc bx
    cmp bx, 6      ;Did we fill chars at +2 +3 +4 +5 ?
    jb  .Next      ;Not yet

因为这个循环中有 4 次迭代,并且数字DX每次旋转 4 倍,DX最终会保持原来的值。无需保存它。


jmp endi;

这是要达到什么目的?这是跳转到data那肯定不是可执行代码!如果你想要一个无限循环,那么只需写:

jmp $

您所说的与其他模块一起使用的另一个文件是一团糟!
大家一直忽视这一点,但BIOS电传打字机功能需要BH注册以获得所需的显示页面。因此使用它总是一个坏主意BX作为字符串指针。
这是一个很好的解决方案,不需要您更改所有现有代码(关于使用BX):

print_string:
    pusha
    mov     si, bx
    mov     bh, 0      ;Display page 0
    ;mov     bl, 7      ;Color if this were a graphical screen
    cld                ;Required to use LODSB correctly
    jmp     .start
  .write:
    mov     ah, 0x0E   ;BIOS.Teletype
    int     0x10
  .start:
    lodsb              ;Increments the pointer automatically
    cmp     al, 0      ;Comparing for null
    jne     .write
    popa
    ret
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NASM 模块将十六进制转换为字符串并打印出来。已组装但未按预期工作 的相关文章

  • 大会,你好世界问题

    我正在 Linux 上学习 asm noobuntu 10 04 我得到了以下代码 http asm sourceforge net intro hello html http asm sourceforge net intro hello
  • 弹出 x86 堆栈以访问函数 arg 时出现分段错误

    我正在尝试链接 x86 程序集和 C 我的C程序 extern int plus 10 int include
  • 从 exe 文件中获取汇编级代码?

    我当时正在做linux汇编编程 在过去的几天里我已经转而学习windows汇编编程 我在用ml作为我的汇编器和golink作为我的链接器 我有我的汇编代码并已获得我的exe从中 现在我需要取回它的十六进制 xff xab x55等等 在li
  • Linux内核页表更新

    在linux x86 中分页 每个进程都有它自己的页面目录 页表遍历从 CR3 指向的页目录开始 每个进程共享内核页目录内容 假设三个句子是正确的 假设某个进程进入内核 模式并更新他的内核页目录内容 地址映射 访问 权利等 问题 由于内核地
  • 这个反斜杠在这段汇编代码中起什么作用?

    我不确定这些推线有什么区别 修剪下来来自 Linux 的 x86 entry calling h https github com torvalds linux blob 241e39004581475b2802cd63c111fec43b
  • 如何仅使用单个数组在 JavaScript 中模拟调用堆栈

    我正在看维基百科页面 https en wikipedia org wiki Call stack在调用堆栈上 并尝试理解这个图像 据我所知 哈哈 const memory memory 0 3 top of stack pointer m
  • 为什么我的代码显示垃圾?

    当我也想打印列表中的每个数字时 我的代码显示垃圾 有什么问题吗 输出应如下所示 给定的数组是 2G 4 PT为什么这是垃圾总数是 7 Code ASSUME CS CODE DS DATA SS STK ORG 0000H DATA SEG
  • 在 x86 汇编中将 64 位常量移至内存

    我正在使用 Intel x64 程序集 NASM 编译器 尝试将 0x4000000000000000 常量移至内存 该常量在 ieee 754 标准双精度中应等于 2 0 我正在使用的代码是 define two 0x4000000000
  • 错误 LNK2019:函数 main 中引用的外部符号无法解析

    我正在尝试在 C 中运行我的简单汇编代码 我只有两个文件 cpp 文件和 asm 文件 编译时出现错误 见下文 如果有人可以提供帮助 我将不胜感激 这是我的 main cpp 文件 include
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 为什么在展开的 ADD 循环内重新初始化寄存器会使其运行速度更快,即使循环内有更多指令?

    我有以下代码 include
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我
  • SIMD 和 VLIW 指令是一样的吗?

    SIMD 单指令多数据 和 VLIW 超长指令字 到底有什么区别 其中一个是另一个的子集吗 或者它们是两个完全不同的东西 完全不相关且正交 一台机器可以有一个或两个 或者两者都没有 SIMD 指令可以作为扩展添加到 VLIW ISA 但 V
  • 整数溢出问题

    我不断遇到整数溢出问题 我不知道如何解决它 有人可以帮忙吗 edx 包含 181 eax 包含 174 xor eax edx mov edx 2 div edx 假设你谈论的是x86 div edx这实际上没有意义 32位div将edx
  • movzbl(%rdi, %rcx, 1), %ecx 在 x86-64 汇编中意味着什么?

    我想我明白 movzbl rdi rcx 1 ecx 意思是 将零扩展字节移至长整型 并表示将 ecx 扩展为 32 位 但我不完全确定语法 rdi rcx 1 指的是什么 我在某处看到该语法指的是 Base Index Scale 但我找
  • Grub 和进入实模式(低级汇编语言编程)

    我一直在开发一个玩具操作系统 并一直使用 grub 作为我的引导加载程序 最近尝试使用 VGA 时 我发现无法使用硬件中断 我发现这是因为我被 grub 置于保护模式 有人知道如何在不删除 grub 的情况下回到实模式吗 如果您使用 GRU
  • 将字段中的位扩展到掩码中所有(重叠+相邻)集位的最快方法?

    假设我有 2 个名为 IN 和 MASK 的二进制输入 实际字段大小可能是 32 到 256 位 具体取决于用于完成任务的指令集 每次调用时两个输入都会改变 Inputs IN 1100010010010100 MASK 000111101
  • Clang 编译器 (x86):80 位长双精度

    我正在尝试在 x86 Windows 平台上使用本机 80 位长双精度 海湾合作委员会选项 mlong double 80 https gcc gnu org onlinedocs gcc x86 Options html似乎不适用于 cl
  • Intel:序列化指令和分支预测

    英特尔架构开发人员手册 http www intel com content www us en architecture and technology 64 ia 32 architectures software developer v

随机推荐