- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我阅读了关于 nasm 的教程,有一个代码示例显示了整个 ascii 字符集。除了为什么我们要推送 ecx 和弹出 ecx 之外,我几乎了解所有内容,因为我看不到它与其余代码的关系。 Ecx 的值为 256,因为我们想要所有字符,但不知道在哪里以及如何使用它。当我们 push 和 pop ecx 时到底发生了什么?为什么我们要把achar的地址移到dx?我没有看到我们使用 dx 做任何事情。我知道我们需要增加 achar 的地址,但我很困惑增量与 ecx 和 dx 的关系。我会很感激一些见解。
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
call display
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
display:
mov ecx, 256
next:
push ecx
mov eax, 4
mov ebx, 1
mov ecx, achar
mov edx, 1
int 80h
pop ecx
mov dx, [achar]
cmp byte [achar], 0dh
inc byte [achar]
loop next
ret
section .data
achar db '0'
最佳答案
I understand pretty much everything
why are we pushing ecx and popping ecx as I dont see how it relates to the rest of the code. Ecx has the value of 256 since we want all chars but no idea where and hows its used.
LOOP
指令使用(这不是一个好主意:
Why is the loop instruction slow? ),它将递减
ecx
,并在 value 大于零时跳转,即它是一个倒计时循环机制。
int 0x80
服务调用需要
ecx
作为内存地址值,因此计数器由
push
/
pop
保存/恢复。一种更高效的方法是将计数器值放入一些备用寄存器中,例如
esi
,然后执行
dec esi
jnz next
。更高效的方法是重新使用字符值本身,如果输出将从零值开始,而不是零数字,那么
inc byte [achar]
之后的零标志可用于检测循环条件。
achar db '0'
48
)开始,对我来说似乎很奇怪,我会从零开始。但这还有一个警告,linux 控制台 I/O 编码是由环境设置的,现在在任何常见的 linux 安装上都是 UTF8,因此有效的可打印单字节字符的值只有 32-126(与普通的 7位 ASCII 编码,使这部分示例工作良好),值 0-31 和 127 是不可打印的控制字符,也与常见的 7b ASCII 编码相同。值 128-255 表示 UTF8 编码的多字节字符(例如:
ř
是两个字节
0xC5 0x99
),作为单个字节,它们是无效的字节序列,因为缺少 UTF8“代码点”字节的剩余部分。
\r
和
\n
控制字符,它们对于 VGA 来说只是另一种字体字形,而不是换行符和换行符控制字符(该含义是由 BIOS/DOS 服务调用创建的,而不是输出
\n
字符将移动内部光标到下一行并丢弃输出中的字符)。
'0'
(
48
) 开始,直到值
126
它输出正确的可打印 ASCII 字符,在
126
之后它输出“某物”,并且由于这些字节有时会形成无效的 UTF8 编码,我会在技术上称之为具有未定义行为的“虚假”输出,对于不同的 linux 版本和控制台设置,您可能会得到不同的结果。
achar: db '0'
,当您不小心使用指令助记符作为标签时,如
loop:
或
dec: db 'd'
,这将节省您的时间。
mov dx, [achar]
dx
不再使用,因此这是无用的指令。
cmp byte [achar], 0dh
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
call display
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
; displays all valid printable ASCII characters (32-126), and new-line after.
display:
mov byte [achar], ' ' ; first valid printable ASCII
next:
mov eax, 4
mov ebx, 1
mov ecx, achar
mov edx, 1
int 0x80
inc byte [achar]
cmp byte [achar], 126
jbe next ; repeat until all chars are printed
; that will output all 32..126 printable ASCII characters
; display one more character, new line (reuse of registers)
mov byte [achar], `\n` ; NASM uses backticks for C-like meta chars
mov eax, 4 ; ebx, ecx and edx are already set from loop above
int 0x80
ret
section .bss
achar: resb 1 ; reserve one byte for character output
section .text
global _start ;makes symbol "_start" global (visible for linker)
_start: ;linker's default entry point
call display
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
; displays all valid printable ASCII characters (32-126), and new-line after.
display:
; prepare in memory string with all ASCII chars and new-line
mov al,' ' ; first valid printable ASCII
mov edi, allAsciiChars
mov ecx, edi ; this address will be used also for "write" int 0x80
nextChar:
mov [edi], al
inc edi
inc al
cmp al, 126
jbe nextChar
; add one more new line at end
mov byte [edi], `\n`
; display the prepared "string" in one "write" call
mov eax, 4 ; sys_write, ecx is already set
mov ebx, 1 ; file descriptor STDOUT
lea edx, [edi+1]; edx = edi+1 (memory address beyond last char)
sub edx, ecx ; edx = length of generated string
int 0x80
ret
section .bss
allAsciiChars: resb 126-' '+1+1 ; reserve space for ASCII characters and \n
nasm -f elf32 -F dwarf -g test.asm -l test.lst -w+all
ld -m elf_i386 -o test test.o
$ ./test
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
关于assembly - 在 linux 控制台中显示所有 ascii 字符(NASM 程序集),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48046707/
我刚刚在学习 NASM,我有点想弄清楚这个问题。你如何在 NASM 中声明变量?例如,如何在 NASM 中声明 unsigned int i?谢谢 最佳答案 汇编语言中没有 unsigned int
我正在阅读这篇关于操作系统编程的精彩脚本 http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf 第 12 页有一
我正在尝试使用 nasm 打印给我的程序的命令行参数: GLOBAL main EXTERN printf section .rodata fmt db "Argument: %s", 10, 0 s
这两种工具都将汇编指令直接翻译成机器代码,但是否有可能确定哪一种产生最快和最干净的代码? 最佳答案 当您使用汇编程序编写时,您准确地描述了生成 的说明所以它不依赖于汇编程序。这取决于你。您编写的助记符
代码: %define x 0x03 x equ 0x03 它们之间有什么区别? 最佳答案 %define是一种更强大的宏处理方式,类似于 C 预处理器。在您的简单情况下,使用 x 没有太大区
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 关闭 8 年前。 这个问题似乎是题外话,因为它缺乏足够的信息来诊断问题。更详细地描述您的问题或inclu
我目前正在关注 a tutorial on OS development ,其中包括对引导加载程序的讨论。 我的引导加载程序当前处于 16 位实模式,因此,我能够使用提供的 BIOS 中断(例如 VG
len: equ 2 len: db 2 它们是否相同,产生的标签可以代替2使用?如果不是,那么每种声明形式的优点或缺点是什么?它们可以互换使用吗? 最佳答案 第一个是equate,类似于C
我的循环有问题,其中包含的代码很长,它给了我错误“短跳超出范围”,所以我想知道是否有一种方法可以通过不减少来使循环工作其中代码量有多少? 示例1: label: my code LOOP la
在阅读了至少约4本关于汇编编程的不同书籍的前3或4章之后,我进入了一个阶段,可以使用MASM 6.11将“Hello World”放置在dosbox控制台上。想象一下我的喜悦! 我程序的第一个版本使用
我正在做一个项目,将我编写的子程序附加到老师包含的主文件中。他给了我们使我们的子程序成为全局性的说明,但显然我是个白痴。这两个 asm 文件在同一个文件夹中,我正在使用 nasm -f elf -g
我最近开始使用 NASM 程序集编写代码,但我的问题是我不知道如何以正确的方式访问结构元素。我已经在这个网站和谷歌上搜索了解决方案,但我看到到处都有人说不同的话。我的程序崩溃了,我感觉问题出在访问结构
我正在尝试从用户那里获取输入,然后我想根据用户输入的内容输出一些文本。 我的问题是出于某种原因,它总是认为它是 A,我不知道为什么。你可以在下面找到我的代码: bits 16
我熟悉 TASM 但不太熟悉 NASM。我读过 NASM 允许使用本地标签,这些标签在名称前用点表示。例如代码 .loop: ;some code jmp .loop 定义一个局部标号,
您将如何在寄存器上对 NASM 进行位移?我读了手册,似乎只提到了这些运算符 >> , > 和 >仅用于整数常量。这就是“标量值”的含义。您可以使用 shl 移位寄存器中的值或 shr指示。它们用于将
首先,这是一个家庭作业。 我有一个循环来分别获取两位数的值,并通过将第一个数字乘以 10 并与第二个数字相加得到一个整数来加入它们。 我正在做这一切并保存在我的AL注册,现在我想将该整数插入一个数组,
我一直在做基本的 NASM 编码,我想知道是否可以使用 NASM 模拟按键。如果是这样,怎么做? 如果重要的话,我正在使用 Ubuntu linux 10.04 和 Pentium R T4300 处
我可以在 NASM 中创建一个新标签,它指向一个新的内存位置,该位置与另一个标签指向的内存位置偏移几个字节。 例如:如果 label1 指向内存位置 0x40h,有没有办法使用 label1 定义指向
我需要设置一些标签地址/偏移量的最高位。 我试过: 测试.nasm: BITS 32 dw mylabel | 0x8000 mylabel: dd 0 但是当我尝试组装它时,我得到: nasm -f
如果能向我解释以下使用 printf、使用 nasm 和 gcc 编译的示例中发生了什么,我将不胜感激。为什么“sud”只打印在屏幕上?我也不明白,当我将“push 'sud'”与“push 'sud
我是一名优秀的程序员,十分优秀!