The First Program: Unterschied zwischen den Versionen

Aus C und Assembler mit Raspberry
Die Seite wurde neu angelegt: „Our first program will initially do nothing; it will simply run an infinite loop. We use it as a foundational building block to create all further experiments. I will first describe how such a program is created, what peculiarities there are, how it is compiled, and then how it is executed. == Creating the Source Code == First, we open our text editor to write our first assembly program. <syntaxhighlight lang="asm"> /* The first program 13.10.2020 www.s…“
 
Zeile 52: Zeile 52:
!DESCRIPTION
!DESCRIPTION
|-
|-
|.text |Executable program code
|.text
This section contains read-only data and cannot be written to
|Executable program code
This section contains read-only data and cannot be written to
|-
|-
|.data |Data
|.data
Within this section, data can be read and written. The data is not executable
|Data
Within this section, data can be read and written. The data is not executable
|-
|-
|.rdata |Similar to .data, but the data cannot be written. This is used, for example, for constants.
|.rdata
|Similar to .data, but the data cannot be written. This is used, for example, for constants.
|-
|-
|.init |Generates code that is only executable at the start of the program.
|.init
|Generates code that is only executable at the start of the program.
|}
|}
== .globl ==
== .globl ==
In line 6, the label _start is defined as global. This makes the linker aware of this label. In our system, which we must program here, we need to define this label as global so the linker can place our code in memory at address 0x8000. For 32-bit bare-metal applications, the Raspberry Pi expects the program to be exactly there. This is due to the peculiarity of the Raspberry Pi. The Raspberry Pi initially doesn't start with the CPU, but with its graphics chip. A firmware is started there, the Raspberry Pi is initialized, and only then handed over to the CPU. During this time, this memory space is reserved, and the CPU is then assigned to look at memory location 0x8000 and execute the code there. For 64-bit bare-metal applications, the address is 0x80000.
In line 6, the label _start is defined as global. This makes the linker aware of this label. In our system, which we must program here, we need to define this label as global so the linker can place our code in memory at address 0x8000. For 32-bit bare-metal applications, the Raspberry Pi expects the program to be exactly there. This is due to the peculiarity of the Raspberry Pi. The Raspberry Pi initially doesn't start with the CPU, but with its graphics chip. A firmware is started there, the Raspberry Pi is initialized, and only then handed over to the CPU. During this time, this memory space is reserved, and the CPU is then assigned to look at memory location 0x8000 and execute the code there. For 64-bit bare-metal applications, the address is 0x80000.

Version vom 1. April 2025, 12:19 Uhr

Our first program will initially do nothing; it will simply run an infinite loop. We use it as a foundational building block to create all further experiments. I will first describe how such a program is created, what peculiarities there are, how it is compiled, and then how it is executed.

Creating the Source Code

First, we open our text editor to write our first assembly program.

/*
The first program
13.10.2020 www.satyria.de
*/
.section .init    @This shows the linker what to consider
.globl _start     @Generates a global label
_start:           @The label _start (entry address)

b main            @Branch to "main"

.section .text    @Instruction to the linker that code is coming

main:             @Create the label "main"
   mov sp,#0x8000 @Create a stack of 32768 bytes

MainLoop:         @Infinite loop 
   b MainLoop

erstes.s

Save this file in the default installation directory on Windows as follows: C:\msys64\home\xxx, where "xxx" usually refers to your name. On Linux, it can be saved in the "Home" directory. Name it erstes.s. The suffix .s designates the file as assembly source code.

First, I will describe the program and the commands used, and in the end, we will compile it.

Comments

In this example, I have highlighted the comments in orange so that they can be better recognized. In the following examples, these will be shown in olive.

There are two types of comments. Comments that span multiple lines start with /* and end with */. This can be seen in lines 1-4 in the example.

In the following lines, @ is used to create a line comment. The comment starts from the @ character and ends at the end of the line.

Sections

Sections in assembly are needed to tell the linker how to handle the following lines.

Our first .section command (line 5) generates an initiation of the program. This code is executed first but should not be called again afterwards. In this section, we jump to our main program.

In line 11, we use the .text section. This information tells the linker that it is executable code. This part is also write-protected.

Here is a selection of possible .section commands:

SECTION NAME DESCRIPTION
.text Executable program code

This section contains read-only data and cannot be written to

.data Data

Within this section, data can be read and written. The data is not executable

.rdata Similar to .data, but the data cannot be written. This is used, for example, for constants.
.init Generates code that is only executable at the start of the program.

.globl

In line 6, the label _start is defined as global. This makes the linker aware of this label. In our system, which we must program here, we need to define this label as global so the linker can place our code in memory at address 0x8000. For 32-bit bare-metal applications, the Raspberry Pi expects the program to be exactly there. This is due to the peculiarity of the Raspberry Pi. The Raspberry Pi initially doesn't start with the CPU, but with its graphics chip. A firmware is started there, the Raspberry Pi is initialized, and only then handed over to the CPU. During this time, this memory space is reserved, and the CPU is then assigned to look at memory location 0x8000 and execute the code there. For 64-bit bare-metal applications, the address is 0x80000.

The First Assembly Commands

In this example, only two assembly instructions have been used so far, b and mov, highlighted in blue.

b (Branch)

b stands for Branch and means that the program should branch.

b main @Branch to "main"


The first Branch command (line 9) means it should jump to the label main, thereby starting our program.

MainLoop: @Infinite loop

  b MainLoop


The second Branch command used here means it should jump to the label MainLoop. If you look at the code closely, you will see that a constant jump to the same code section occurs. This creates an infinite loop. We must do this here because otherwise, the program would do something undefined, possibly things we do not want.

A Note on Labels

All labels that are jumped to must be concluded with : in the code. All alphanumeric characters plus a few special characters are allowed. Ideally, one should use meaningful labels so that the code remains readable later on.

mov (Move)

  mov sp,#0x8000  @Create a stack of 32768 bytes


The command mov means that information should be moved. In our case, we write the address 0x8000 into the stack pointer (sp) register. We need the stack later in our programs to store temporary data.

A stack operates in a way that the last number placed on it is the first one taken off (LIFO). The stack pointer (sp) negates its position, meaning the first number is stored at memory location 0x8000, and the next at 0x7FFF.

In our case, we reserve memory from 0 to 0x8000 for the stack.

I will describe the mov command in more detail later on; for now, let's just see it in action.

Number Formats

In the example mov, I used the "number" 0x8000. In the comment, the number 32768 is shown. These two numbers are identical. The prefix 0x is used to indicate a hexadecimal number. Without specifying a format, the compiler interprets the number as a decimal. Besides these two formats, there are a few others. Here’s a list:

NUMBER TYPE BASE PREFIX ALLOWED CHARACTERS Decimal 10 - 0-9 Hexadecimal 16 0x or 0X 0-9, A-F Octal 8 O 0-7 Binary 2 0b or 0B 0-1 Floating Point 10 0f or 0F 0-9

The translation has been completed and the content appears accurate. No changes have been noted that would necessitate a summary of modifications.