它是确定使用BX寄存器保存一个指数? [英] Is it ok to use bx register to save an index?

查看:136
本文介绍了它是确定使用BX寄存器保存一个指数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在装配过程中一个任务来计算字符串中的字数,我需要保存我的CX寄存器的答案。 (IM工作的80×86处理器)

I have a task in assembly course to count the number of words in a string, and I need to save my answer in cx register. (im working on 80x86 processor)

所以,我心中已经设置:

So I'v set:

CX为0 - 这将是我的柜台

cx to 0 - this will be my counter

BX为0 - 这将是我的指数

bx to 0 - this will be my index

和我想知道如果我正确地使用它,这是我的code:

And I want to know if I use it properly, this is my code:

.model small 
.stack 100h
.data

A db '  this   is  a  test  $'

B db 100 dup('$')

.code
    mov ax, @data
    mov ds, ax

    mov cx, 0 
    mov bx, 0

looping:
    cmp A[bx], ' '
    jne foundchar
    inc bx
    jmp looping


foundchar:
    inc bx
    cmp A[bx], ' '
    je foundword
    cmp A[bx], '$'
    je soff
    jmp foundchar



foundword:
    inc cx
    inc bx
    jmp looping

soff:
    .exit

end

和别人从我的阶级都不同的看法,她设置SI为A的偏移...
我并没有真正理解这个解决方案:

And someone else from my class did it differently, she set si to the offset of A... and I didn't really understand this solution:

mov cx,0
mov si, offset A

mov dl,0


next2:
    inc si
    mov dl,[si]
    cmp dl,"$"
    JE soff
    cmp dl, " "
    JE test1 ;if the char is space so lets check what is before the char
    jmp next2 ; if the char no space jump back to the loop

test1:
mov al,[si-1]
cmp al, ' '
je  next2
add cx,1
jmp next2

soff:
mov al,[si-1]
cmp al,' '
je sofsofi
add cx,1

sofsofi:

.exit
end 

请帮我理解,什么是做它更合适的方式。

Please help me to understand it, and what would be the more proper way to do it.

配发

推荐答案

要回答的问题在标题:不,它是不行的使用BX作为指标。使用目标指数或来源指数(取决于是否写入或读取数据)。使用BX的工作,但它不被视为最佳实践为DI和SI的目的是持有索引。

To answer question in title: No. It is not okay to use BX as index. Use Destination Index or Source Index (depending of whether you write or read data). Using BX will work, but it is not considered "best practice" as DI and SI purpose is to hold indexes.

而现在的解释是:

虽然( 86 )寄存器被命名,你可以(当然是有一定的限制)使用他们的任务与他们的名字碰撞,但它可以导致错误和跨$ p $问题pting您code。

Although (x86) registers are named, you can (with certain limitations of course) use them for task colliding with their names but it can lead to mistakes and problems with interpreting your code.

我会尽量在这里写一个简单的指南到寄存器初学者。

I will try to write here a simple guide to registers for beginners.

限制:


  • 某些操作读写从/到特定的寄存器,例如数据。
    MUL用途(E)AX和(E)DX,所以你必须确保不存储数据
    你的程序仍需要(或推后来弹出他们)在寄存器
    将被修改。

  • 不是每一个寄存器给你(直接)访问8位的部分。

  • 有些寄存器有凉爽的特殊功能,所以为了不
    妥协的人,你需要正确地使用它们。

记住下面列出的所有寄存器可以扩展(32位)的形式加入E至名称中使用(如:EAX是蓄电池,其中低16个字节包含16位AX的32位版本)。寄存器将按照重要性顺序列出(从初学者的角度)。

Remember that all registers listed below can be used in Extended (32bit) form by adding E to name (eg. EAX is 32bit version of Accumulator, where lower 16 bytes contains 16bit AX). Registers will be listed in order of importance (from perspective of beginner).


  1. AX - 累加寄存器通常用作主要参数和结果。在简单得多的日子,86还是要
    听说处理器通常有对参数,例如两个寄存器。
    X和Y上的Commodore 64,和累加器存储结果。在
    总之,它的名字是现在大多的历史,它通常会
    先登记您使用几乎所有 - 例如
    算术/逻辑运算和 DOS(21H)中断内搭
    通过AH(AX的高字节)的说法。除了操作的
    需要通过价值AX传递你可以把它作为一个主要的
    变量。

  2. DX - 数据寄存器 - 这里不多介绍,它存储的数据。我决定AX之后列出,是因为这两个作品一起
    经常 - 例如MUL(乘法)使用DX存储数据
    从AX溢出。所以,是的,它只是辅助变量。

  3. CX - 计数寄存器 - 也相当简单,它只不过是另一种通用寄存器。而这一次它被用来
    特别是作为计数器(如名字所暗示的)通过诸如操作
    循环(LOOP系列操作数)和字符串指令(REP家庭
    操作数)。只要你不使用修改CX指令
    你可以自由地使用它为任何你需要的(但总是检查
    有您的数据没有更好点)。

  4. BX - 基址寄存器 - 长话短说,因为32位来到这个寄存器失去了它的抵消的内存地址的目的。所以
    它是免费的寄存器,它的存在主要是为落后
    兼容性。可怜的家伙。请使用它,不要让历史的迷雾
    吞吃这样的小勇敢烤面包机注册。

  1. AX - accumulator register is typically used as primary parameter and result. In much simpler days when x86 was still to be heard about processors usually had two registers for parameters, eg. X and Y on Commodore 64, and Accumulator for storing result. In short, its name is now mostly historical and it will usually be first register you use for virtually everything - for example arithmetic/logic operations and DOS (21h) interrupts which take argument via AH (higher byte of AX). Aside of operations that require value to be passed via AX you can consider it as a primary variable.
  2. DX - data register - not much to describe here, it stores data. I decided to list it after AX because those two works together quite often - for example MUL (multiplication) uses DX to store data overflowing from AX. So yeah, its "just" secondary variable.
  3. CX - counter register - also quite simple, it is just another general purpose register. This time however it is used specifically as counter (as name implies) by operations such as loops (LOOP family operands) and string instructions (REP family operands). As long as you are not using instructions that modify CX you are free to use it for whatever you need (but always check if there are no better spots for your data).
  4. BX - base register - long story short, since 32bit arrived this register lost its purpose of "offsetting" memory addresses. So it is "free" register which exists mostly for backward compatibility. Poor guy. Please use it, do not let mists of history devour such little brave t̶o̶a̶s̶t̶e̶r̶ register.

故宫登录!是,有这样的人。


  1. SP BP - 堆栈和基址指针 - 默认的方法是不能直接使用它们,这些是由PUSH处理,
    管理堆栈,让你的POP,CALL和RET指令
    使用的功能。然而,它们可以用于异端花样接壤
    用黑暗魔法,你敢亵渎神圣的堆栈帧?更改
    这些寄存器的值可能会导致真正的堆栈溢出。不使用
    除非你真的确定你想要它(并知道如何)。 (在一定条件下可以BP成为另一个自由这样注册BX但让我们忽略它)

  1. SP and BP - stack and base pointers - default approach is to not use them directly, those are handled by PUSH, POP, CALL, and RET instructions for managing stack and allow you to use functions. However they can be used for heretic tricks bordering with dark magic, do you dare to desecrate holy stack frame? Changing values of those registers can cause real stack overflow. Do not use unless you really, really sure you want it (and know how). (In certain conditions BP can become another "free" register like BX but lets ignore it for now)

现在开始吓人寄存器的部分,与恐吓名称和复杂的操作依赖于它们。也有是他们没有更高和更低的8bit部分提供(但你仍然可以使用位掩码来提取他们如果需要的话)。

Now starts the part of scary registers, with intimidating names and complicated operations tied to them. Also there is no Higher and Lower 8bit part of them available (but you can still use bit mask to extract them if needed).


  1. DI SI - 目的地和来源分类指数 - 这两个被用作指针内存块(缓冲区/数组/串
    等),用于自动数据复制/ REP与操作或其他书面形式
    基于字符串/数组的。如果你不使用这样的困惑
    操作,那么你可以使用DI和SI作为数据寄存器,用
    不能够限制(容易)选择更低或更高的
    字节。基于循环操作完美的选择。

  2. 段寄存器 - CS,SS,DS,ES,FS,GS ......(伊克Nowdays它的一个
    他们的全军) - 虽然故事可以很长,有
    简短的解释 - 两个主要部分是code段和数据
    分割。 code段包含code(奇怪吧?),所有
    数据你就在这声明。段经常一起使用以
    DI和SI寄存器用于复制数据 - 例如LODSD预计SI
    总之点在数据段的内存地址,因此
    (平)code,有必要先告知CPU您的数据和
    code段之一。你真的不应该使用
    这些寄存器或者分段错误会踢你的
    脸。

  1. DI and SI - destination and source index - those two are used as pointers to memory blocks (buffers/arrays/strings etc) for automated data copying/writing with REP operation or other string/array based ones. If you are not using such confusing operations then you can use DI and SI as data registers, with limitation of not being able to (easily) select lower or higher byte. Perfect choice for loop based operations.
  2. Segment registers - CS, SS, DS, ES, FS, GS... (eek! Nowdays its a whole army of them) - Although story can be very long, there is short explanation - two main segments are Code Segment and Data Segment. Code Segment contains code (surprising, right?) and all data you declared right in it. Segments are often used together with DI and SI registers for copying data - for example LODSD expects SI to point at memory address in Data Segment, therefore in short ("flat") code it is necessary to first inform CPU that your Data and Code segments are one. You really should not use those registers or else Segmentation Fault will kick you in the face.

您可以阅读更多的像这整齐指南

至于你的code很少有建议我可以给你,现在(您的脚本的总大修则需要等待明天或星期一,因为我有点儿忙这个周末)

As for your code there are few advices I can give you right now (For total overhaul of your script you will need to wait for tomorrow or Monday as I am kinda busy this weekend)

使用SI / DI更好。在您的code A [BX]等价于(A内存地址)+(以SI值),CPU是非常简单的生物,因此preFER简单[SI],而不是在飞行做数学。

Using SI/DI is better. In your code A[bx] is equivalent to (A memory address)+(value in SI), CPU is very simple creature so it prefer simple [SI] instead of doing math on the fly.

这是你设置数据段你自己,因为它是达到环境(系统/ CPU /仿真器)件好事设置初始值。虽然它是用段专用内容的好习惯就可以了,对于这样简单的程序,随意存储数据位在code段,它甚至会执行速度同比降低内存跳跃和地址计算。
然后,你可以这样写:
MOV AX,CS
MOV DS,AX
(不能直接做)。这是保证为code段是一个与你目前的code(否则将不执行)。

It is good thing that you set Data Segment on your own as it is up to environment (system/cpu/emulator) to set initial value. While it is good habit to use segments for dedicated content you can, for such simple program, feel free to store a bit of data in code segment, it will even speed execution up by reducing memory jumps and address calculations. Then you can write: MOV AX, CS MOV DS, AX (can't do it directly). It is guaranteed for Code Segment to be the one with your current code (otherwise it wouldn't execute).

归零寄存器可以做出更凉爽!想要把0 AX?使用XOR AX,AX(AX = AX独家或AX,这是逻辑状态总是会产生0)。它不仅是在内存中(小code =更快的加载),它也执行速度比短复制值(和CPU的nowdays有足够的智慧,使其更快)。额外的好处是造型加分。

Zeroing registers can be made much cooler! Want to put 0 in AX? Use XOR AX, AX (AX = AX exclusive or AX, which as logic states will always result in 0). Not only it is shorter in memory (smaller code = faster loading), it also executes faster than copying value (and CPU's nowdays are smart enough to make it even faster). Additional advantage are style points.

计数器为结果呢?那么,计数寄存器被制成循环计数不是数据计数器。用于存储数据DX或BX更直观(BX比DS更多,因为没有什么需要的数据在本登记了,所以它的只是变量)。但是,如果需要结果CX那么你必须服从,我猜。

Counter as result? Well, counter register is made as loop counter not data counter. For storing data DX or BX more intuitive (BX more than DS, as nothing requires data in this register anymore so its "just variable"). But if result in CX is required then you must obey, I guess.

好吧,这就是今晚。如果有什么不清楚发表评论。

Well, that's all for tonight. If something is unclear leave a comment.

这篇关于它是确定使用BX寄存器保存一个指数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆