汇编语言写代码_让我们写一些汇编语言代码!

本文引导读者开始学习和编写汇编语言代码,通过实践理解其基本概念。
摘要由CSDN通过智能技术生成

汇编语言写代码

学习大会—第4.1部分 (Learning Assembly — Part 4.1)

By looking at some simple examples, we can learn how to write Assembly Language code.

通过查看一些简单的示例,我们可以学习如何编写汇编语言代码。

Assembly is a very low-level programming language - everything you write is “close to the metal”. What this means is that the language is very related to the hardware it is on. In this article, we will learn how to write a variant of Assembly language. Specifically, we will be looking at 6502 Assembly Language. The 6502 is a classic processor, found in lots of old tech. Don’t let age worry you though, the core tenets of Assembly will be the same whether we are looking at a 6502 or and intel i7.

汇编是一种非常底层的编程语言-您编写的所有内容都“接近金属”。 这意味着该语言与其所处的硬件非常相关。 在本文中,我们将学习如何编写一种汇编语言。 具体来说,我们将研究6502汇编语言。 6502是经典处理器,在许多旧技术中都可以找到。 不过,不要让年龄担心,无论我们使用的是6502还是Intel i7,Assembly的核心宗旨都是相同的。

To learn how to write this code we will take a look at two small examples. The examples have been picked to give us a brief idea of the basic features of the language. We will also look at how we can make our code more readable by using features that the Assembler can provide us.

要学习如何编写此代码,我们将看两个小例子。 选取示例以使我们对语言的基本功能有一个简短的了解。 我们还将研究如何使用汇编程序可以为我们提供的功能使代码更具可读性。

Technically, this is Part 4 of a “learning assembly” series I am writing. However, wherever possible I am trying to ensure each part is independent. If all you’re interested in is getting the basics of assembly, hopefully, this will be suitable for you as well.

从技术上讲,这是我正在编写的“学习程序集”系列的第4部分。 但是,我会尽可能地确保每个部分都是独立的。 如果您只想了解组装的基础知识,希望它也适合您。

Let’s begin with a very brief recap of the 6502 hardware.

让我们首先简要回顾一下6502硬件。

简要回顾 (A Small Recap)

An Assembly Language could be defined by its instruction set. An instruction is a command that the processor will be able to interpret (like add, or to move something around in memory). The instructions available to us are deeply linked to the hardware itself. Using a 6502 processor gives us access to around 50 instructions. Outside of these 50 instructions, if we want the processor to do something, we will need to create it ourselves.

汇编语言可以由其指令集定义。 指令是处理器将能够解释的命令(例如添加或在内存中移动某些内容)。 我们可以使用的说明与硬件本身紧密相连。 使用6502处理器使我们可以访问大约50条指令。 在这50条指令之外,如果我们希望处理器做某事,我们将需要自己创建它。

A deeper dive into the 6502 hardware is available here, but we can go over some things that may be important for us today:

您可以在此处更深入地了解6502硬件,但是我们可以讨论一些对于今天对我们来说可能很重要的事情:

The Accumulator: This is the part of the 6502 hardware that can help us do arithmetic. If we wanted to add two numbers, we could send them into the accumulator, where they would “accumulate” together.

累加器 :这是6502硬件的一部分,可以帮助我们进行算术运算。 如果我们想添加两个数字,可以将它们发送到累加器中,在那里它们将“累加”在一起。

The Carry Register: Imagine if we did the sum 26 + 15.

进位登记簿 :想象一下,如果我们进行了26 + 15的总和。

 (1) <- our carry
26
+̲ ̲1̲5̲
41

Well, we’ve added 5 and 6, which gives 1, carry-a-1. Then we could do 20 + 10 + the-10-we’ve-carried-over to give 40. Combining these we get the answer of 41.

好吧,我们加了5和6,得到1,进位为a-1。 然后,我们可以做20 + 10 +进位的-10-,得到40。将这些结合起来,我们得到41的答案。

Well, when we add binary numbers something similar happens — we still carry things. However, in 6502 we can only keep track of things that fit in an 8-bit number. If we do some maths that results in us carrying something that won’t fit into 8-bits, we need to keep track of this. For example 1000 0001 + 1000 0000 gives 1 0000 0001. However, we cannot fit the left-most 1 we had to carry into 8-bits, but, we also cannot forget about it if we want our maths to work.

好吧,当我们添加二进制数时,会发生类似的事情-我们仍然可以携带东西。 但是,在6502中,我们只能跟踪适合8位数字的内容。 如果我们做一些数学运算导致我们携带的东西不适合8位,那么我们需要对此进行跟踪。 例如1000 0001 + 1000 0000给出1 0000 0001 。 但是,我们无法将必须携带的最左边的1放入8位中,但是,如果我们希望数学能够正常工作,我们也不会忘记它。

This concept of carrying a number if it falls out of 8-bits is handled by the 6502 hardware in the Carry register. It’s just something we’ll try to keep in mind when we do maths.

如果进位数字不超过8位,则该进位概念由进位寄存器中的6502硬件处理。 这只是我们做数学时要记住的事情。

加成 (Addition)

Our easiest example will be 1 + 2. Here's some code:

我们最简单的示例是1 +2。下面是一些代码:

LDA     #01      
ADC #02
STA $0402

On the left of each line is the instruction while on the right is the data or memory location needed to make the instruction work. This style is how Assembly language is written. Let’s go through the example one line at a time.

每行的左边是指令,而右边是使该指令起作用所需的数据或存储器位置。 这种样式是汇编语言的编写方式。 让我们一次遍历该示例。

Line 1: LDA is telling the 6502 to load the piece of data that follows into the Accumulator (A). Here, it is #01. We can prefix our data with a symbol to tell the assembler what sort of data we are passing it. In this case, we are using a hashtag which means our data is a 'literal' - we are literally passing it a number. After this line, the contents of A is 1.

第1行LDA通知6502将随后的数据加载到累加器(A)中。 在这里,是#01 。 我们可以在数据前添加一个符号,以告诉汇编器我们要传递哪种数据。 在这种情况下,我们使用的是#标签,这意味着我们的数据是“文字”的-实际上是将数字传递给它。 在此行之后,A的内容为1。

Line 2: ADC means to add the following value onto whatever is currently in the Accumulator. The 'C' in the instruction tells us it will be keeping track of any carrys that have happened in previous calculations. Here, we assume C = 0. Therefore, all we are adding to the Accumulator is#02. Now, the value in A is 3.

第2行ADC意思是将以下值加到累加器当前的值上。 指令中的“ C”告诉我们它将跟踪先前计算中发生的任何进位。 在这里,我们假设C =0。因此,我们要添加到累加器中的就是#02 。 现在,A中的值为3。

Line 3: The STA instruction will send the contents of the Accumulator to a location in memory. In our example, this will send the value 3 to the memory address $0402. Note, we have not used a # - this is because it is not literal, it is an address. Furthermore, we have used $ which tells the assembler this value is in binary.

第3行STA指令会将累加器的内容发送到内存中的某个位置。 在我们的示例中,这会将值3发送到内存地址$0402 。 注意,我们没有使用# -这是因为它不是文字,而是地址。 此外,我们使用了$ ,它告诉汇编器该值是二进制的。

After these three instructions, we have successfully done 1 + 2 — well done! If we wanted to view the answer we would have to look in $0402.

按照这三个指示,我们成功完成了1 + 2的工作-做得好! 如果要查看答案,则必须查看$0402

寻址和标志 (Addressing and Flags)

In Part 3, we discussed the numerous registers that could be set in the 6502. These have numerous uses, among them is to keep track of aspects of arithmetic. We also mentioned, above, that ADC will also add anything that has been carried from the last calculation (ie, anything in the carry register). We need to be careful that what is happening is actually what we want to happen. We don’t want to be adding in the Carry when we don’t want to and we don’t want to miss it out if we actually want it. We can manually clear the flags to ensure no unexpected values are involved in our arithmetic - better safe than sorry. This is what CLC (clear carry flag) and CLD (clear decimal flag) do.

在第3部分中,我们讨论了可在6502中设置的众多寄存器。这些寄存器具有多种用途,其中包括跟踪算术方面。 上面我们还提到, ADC还将添加上次计算中已带进的任何内容(即,进位寄存器中的任何内容)。 我们需要注意,正在发生的事情实际上就是我们想要发生的事情。 我们不想在不需要的时候添加进位记录,如果我们确实想要它,也不想错过它。 我们可以手动清除标志,以确保算术运算中不包含任何意外值-安全胜过遗憾。 这就是CLC (清除进位标志)和CLD (清除十进制标志)的作用。

In the previous example, we referred to the values 1 and 2 directly. There, it was ok as we only have a small number of values we need to use in our calculation. However, if we were doing something more involved this would get tiring. In Python, you can call a variable ‘x’ or ‘y’ and use them throughout your code. What is common to do in is to store your values somewhere in memory, then in your code point to that memory location. This will save us explicitly passing values around. For example, the value 1 might be stored in the location $0400 and the value 2 in $0401. Now, we can just refer to them and get the same result as before.

在前面的示例中,我们直接引用了值1和2。 在那里,可以,因为我们只有少量需要在计算中使用的值。 但是,如果我们做更多的事情,这会很累。 在Python中,您可以调用变量“ x”或“ y”,并在整个代码中使用它们。 常见的做法是将值存储在内存中的某个位置,然后在代码中指向该内存位置。 这将避免我们显式传递值。 例如,值1可能存储在位置$0400 ,值2可能存储在$0401 。 现在,我们可以参考它们并获得与以前相同的结果。

Below is some code with these two changes made.

以下是对这两项所做的一些更改的代码。

CLC            
CLD
LDA $0400
ADC $0401
STA $0402

As well as built-in features of the assembly language, functionality can come from the assembler you choose. Here are some useful features available in most assemblers:

除了汇编语言的内置功能之外,功能还可以来自您选择的汇编程序。 以下是大多数汇编器中可用的一些有用功能:

  • You can store values in a "variable". So, you could say ADR1 = $0400 and then whenever you called ADR1 the assembler would understand you meant the address contained within it.

    您可以将值存储在“变量”中。 因此,您可以说ADR1 = $0400 ,然后每当调用ADR1 ,汇编器就会明白您的意思是其中包含的地址。

  • You can leave comments with ";".

    您可以使用“;”留下评论。
  • You can "name" blocks of code. This allows us to refer to it numerous times in our program. We will see an example soon where this can be useful.

    您可以“命名”代码块。 这使我们可以在程序中多次引用它。 我们将很快看到一个示例,该示例可能会有用。

The code below incorporates the above suggestions:

下面的代码结合了以上建议:

    ADR1 = $0400
ADR2 = $0401
ADR3 = $0402
CLC ; clear carry bit
CLD ; clear decimal bit
ADD LDA ADR1 ; load the contents of ADR1 into accumulator
ADC ADR2 ; add the contents of ADR2 to accumulator
STA ADR3 ; save result to ADR3

Now, our simple code uses more features of the language and assemblers. It is hopefully easier to read and will be easier for us to use and build upon.

现在,我们的简单代码使用了语言和汇编程序的更多功能。 希望它更容易阅读,也将使我们更易于使用和建立。

In the future, we will look at how to get this running on your machine. But for now, I think it’s interesting in itself to see how something as simple as addition can be broken down into much smaller pieces.

将来,我们将研究如何在您的计算机上运行它。 但就目前而言,我认为将加法之类的简单事物分解成更小的片段本身很有趣。

小作弊 (A Small Division Cheat)

Before attempting multiplication (next time!) we will have a quick look at dividing by 2. This can be done easily by looking at operations we can perform on binary numbers. Let’s look at what happens if we shift a binary number to the right. The number 16 (0001 0000) becomes 8 (0000 1000) and 56 (0011 1000) becomes 28 (0001 1100). Shifting them to the right is the equivalent of dividing by two! Compared to doing "proper" division and multiplication it is significantly easier. It’s also quite cool, I think!

在尝试乘法(下一次!)之前,我们将快速了解除以2。这可以通过查看我们可以对二进制数执行的运算来轻松完成。 让我们看看如果将二进制数向右移动会发生什么。 16( 0001 0000 )变为8( 0000 1000 ),56( 0011 1000 )变为28( 0001 1100 )。 将它们向右移动等同于除以2! 与“适当的”除法和乘法相比,它要容易得多。 我想这也很酷!

This sort of shifting is made possible by numerous instructions the 6502 has. The instruction set contains 2 shifts and 2 rotates. The following figure shows an example of each:

通过6502拥有大量指令,可以实现这种移位。 指令集包含2个移位和2个旋转​​。 下图显示了每个示例:

How the 6502 LSR and ROL instructions work
Two examples of shift instructions in the 6502 instruction set: ROL and LSR. Made using draw.io
6502指令集中的移位指令的两个示例:ROL和LSR。 使用draw.io制作

ROL rotates the number to the left, with the left-most bit falling into the carry register while the old contents of C move into the right-most bit.

ROL将数字向左旋转,最左边的位落入进位寄存器,而C的旧内容移到最右边的位。

LSR shifts the number to the right. Here though, the right-most bit falls into the carry, but the left-most is replaced by 0. This is what we can use to divide by two.

LSR将数字向右移动。 虽然在这里,最右边的位落入进位,但是最左边的位被0取代。这就是我们可以用来除以2的方法。

These two instructions have equivalents that go in the opposite direction as well. For the meantime, however, ROL and LSR will be necessary for us to do multiplication.

这两条指令也具有相反的方向。 但是,与此同时, ROLLSR对于我们进行乘法将是必需的。

Here is a short example of what division might look like:

这是一个简单的除法示例:

    ADR1 = $0400
CLC ; clear carry bit
CLD ; clear decimal bit
DIV LSR ADR1 ; shift all the bits in ADR1 to the right

结论 (Conclusion)

We have seen two useful examples of code: addition and a simplified version of division. These examples begin to expose us to the range of instructions that are available on the 6502.

我们已经看到了两个有用的代码示例:加法和除法的简化版本。 这些示例开始使我们了解6502上可用的说明范围。

This article used to have around a 20-minute read length but I decided to split it in two for the sake of readability. So, next time, we will be looking at a more complex example: multiplication.

这篇文章以前的阅读时间大约为20分钟,但出于可读性考虑,我决定将其分为两部分。 因此,下一次,我们将看一个更复杂的示例:乘法。

This is the fourth part of my “learning assembly” series.

这是我的“学习大会”系列的第四部分。

This article has been adapted from my personal blog. Most of the content I talk about will come from two main sources: “6502 Assembly Language Programming” by Lance A.Leventhal and “Programming the 6502” by Rodney Zaks.

本文改编自我的个人博客 。 我谈论的大部分内容都来自两个主要来源:Lance A.Leventhal的“ 6502汇编语言编程”和Rodney Zaks的“对6502进行编程”。

翻译自: https://codeburst.io/lets-write-some-assembly-language-code-d8edb9b6c217

汇编语言写代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值