好吧,这个问题听起来很简单,但我很惊讶。在 1 兆字节是大量内存的古代,英特尔试图弄清楚如何使用 16 位来访问 1 兆字节的内存。他们提出了使用段和偏移地址值来生成 20 位地址的想法。
现在,20 位给出了 2^20 = 1,048,576 个可以寻址的位置。现在假设我们访问每个地址位置 1 个字节,我们得到 1,048,576/(1024*1024) = 2^20/2^20 兆字节 = 1 兆字节。好的,明白了。
混乱来了,我们在古老的 8086 中有 16 位数据总线,一次可以访问 2 个字节而不是 1 个,这相当于 20 位地址可以访问总共 2 MB 的数据,对吗?当数据总线为 2 字节宽时,为什么我们假设每个地址只存储 1 个字节?我在这里很困惑。
我已经学习了编译器和汇编语言,所以我想编写自己的汇编程序作为练习。但我有一些问题;
如何计算@DATA 或 OFFSET/ADDR VarA 等段的地址?
以一个简单的汇编程序为例:
.model small
.stack 1024
.data
msg db 128 dup('A')
.code
start:
mov ax,@data
mov ax,ds
mov dx, offset msg
; DS:DX points at msg
mov ah,4ch
int 21h ; exit program without using msg
end
Run Code Online (Sandbox Code Playgroud)
那么汇编器是如何计算段的段地址的@data呢?
它如何知道将什么放入立即数mov dx, offset msg?
compiler-construction assembly masm memory-segmentation x86-16
我对 stack segment (ss) 和 stack pointer (sp) registers 有点困惑。当堆栈为空时,sp 值是否等于 ss 值?我读到当我们将一个字(2 字节)推入堆栈时,sp 减 2,如果第一条语句为真(sp=ss),那么我可以说如果堆栈不为空,堆栈指针的值总是较小或等于堆栈段的值是真的吗??。如果我们影响 sp 的值使其大于 ss 会发生什么?即:mov ss,200h mov sp,400h mov ax,1010h push ax
请纠正任何错误,提前thanx
我正在使用 TASM 1.4,我正在尝试制作一个输出,该输出将在同一屏幕上显示不同颜色的句子。我可以制作一些显示彩色文本的东西,但所有单词都具有相同的颜色。如何制作显示不同颜色的字符串/句子的东西?例如,类似:
Hi, what group would you like to join?
The Founders
The Vox Populi
Run Code Online (Sandbox Code Playgroud)
“嗨,您想加入哪个小组?” 颜色为绿色。“创始人”的颜色是蓝色。“The Vox Populi”被涂成红色,也许我想要另一个闪烁的句子?我只能将它们全部显示为蓝色、红色或绿色。有什么帮助吗?谢谢。
我刚刚开始学习汇编语言,我已经陷入了“在屏幕上显示存储在寄存器中的十进制值”的部分。我使用 emu8086,任何帮助将不胜感激!:)
.model small ;Specifies the memory model used for program to identify the size of code and data segments
org 100h ;allocate 100H memory locations for stack
.data ;the segment of the memory to declare/initialze the variables
var1 db 0006
var2 db 0002
var3 db 0001
.code ;start of the code segment
main proc ;start of the first procedure
mov bl, var1
add bl, var2
add bl, var3
mov ah, 00h ; display function here?
mov dl, bl ; …Run Code Online (Sandbox Code Playgroud) 我必须使用EMU8086在汇编中做一个简单的计算器,但每次我尝试启动它时,EMU8086都会出现此错误:
Run Code Online (Sandbox Code Playgroud)INT 21h, AH=09h - address: 170B5 byte 24h not found after 2000 bytes. ; correct example of INT 21h/9h: mov dx, offset msg mov ah, 9 int 21h ret msg db "Hello$"
我检查了其他东西,但没有错误:
data segment
choice db ?
snum1 db 4 dup(?)
snum2 db 4 dup(?)
sres db 4 dup(?)
num1 db ?
num2 db ?
res db ?
;;menu1 db "Chose a function to procced", 10, 13, "Add [+]", 10, 13, "Sub [-]", 10, …Run Code Online (Sandbox Code Playgroud) 下一个程序中的输入工作正常,但是当我要求显示输出时,DOS 根本不显示任何内容!这怎么可能?
ORG 256
mov dx, msg1
mov ah, 09h ;DOS.WriteString
int 21h
mov dx, buf
mov ah, 0Ah ;DOS.BufferedInput
int 21h
mov dx, msg2
mov ah, 09h ;DOS.WriteString
int 21h
mov dx, buf
mov ah, 09h ;DOS.WriteString
int 21h
mov ax, 4C00h ;DOS.TerminateWithExitcode
int 21h
; --------------------------------------
msg1: db 'Input : ', '$'
buf: db 20 dup ('$')
msg2: db 13, 10, 'Output : ', '$'
; --------------------------------------
Run Code Online (Sandbox Code Playgroud) 每当我尝试这样做时,在DOSBox下使用MASM 6.15:
mov al, [cx]
Run Code Online (Sandbox Code Playgroud)
要么
mov al, [cx + bx]
Run Code Online (Sandbox Code Playgroud)
要么
mov al, [cx + 4]
Run Code Online (Sandbox Code Playgroud)
我收到错误:'只允许基本或索引注册'
但话说回来,让我说我有一个数组var1.如果我做:
.model small
.stack 4096
.data
var1 BYTE 1, 2, 3, 4, 5, 6, 7, 8, 9
.code
main proc
mov ax, @data
mov ds, ax
mov cx, 5
mov al, [var1 + cx]
mov ah, 4Ch
int 21h
main endp
end main
Run Code Online (Sandbox Code Playgroud)
它工作得很好.为什么不给出与上面相同的错误?CX不是基址或索引寄存器.
[]运算符的整个工作本质是什么?
假设我想将堆栈初始化为S字节大小。
我想选择堆栈的基本位置,B以便随着堆栈从 向下增长B,我最终不会覆盖引导加载程序或 BIOS 使用的任何代码或其他内存。
由于我自己编写引导加载程序(并且初始 MBR 扇区被加载到线性地址0x7c00),防止与引导加载程序发生冲突似乎是一个仔细规划的问题。
我如何知道 BIOS 代码所在的位置,以及我的堆栈是否可能覆盖 BIOS 正在使用的任何内存?
另外,是否可以保证初始ss:sp值指向哪里,以及在不设置新值的情况下可以安全使用多少堆栈空间?
这个问题的灵感来自另一个论坛上某人提出的问题。在以下代码中,扩展内联程序集约束Rah和Ral含义是什么。我以前没见过这些:
#include<stdint.h>
void tty_write_char(uint8_t inchar, uint8_t page_num, uint8_t fg_color)
{
asm (
"int $0x10"
:
: "b" ((uint16_t)page_num<<8 | fg_color),
"Rah"((uint8_t)0x0e), "Ral"(inchar));
}
void tty_write_string(const char *string, uint8_t page_num, uint8_t fg_color)
{
while (*string)
tty_write_char(*string++, page_num, fg_color);
}
/* Use the BIOS to print the first command line argument to the console */
int main(int argc, char *argv[])
{
if (argc > 1)
tty_write_string(argv[1], 0, 0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
特别是在这段代码中使用Rah和Ral作为约束:
asm ( …Run Code Online (Sandbox Code Playgroud)