Assembly Language Study Notes
Assembly Language Overview
Assembly language is defined as a textual representation of machine instructions.
Before building a processor, understanding the semantics of various machine instructions is fundamental.
Assembly languages are ISA- (Instruction Set Architecture) specific and compiler framework specific; thus, many variants exist.
This chapter aims to discuss the principles of assembly languages, provide a rigorous overview, and design a new assembly language (SimpleRisc).
Chapter Structure
Section 3.1: The need for assembly language from both software developers' and hardware designers' perspectives.
Section 3.2: Discuss the generic semantics of assembly languages.
Section 3.3: Design SimpleRisc assembly language and encoding methods.
Chapters 4 & 5: Detail ARM and x86 assembly languages, respectively.
3.1 Why Assembly Language
3.1.1 Software Developer’s Perspective
Humans understand natural languages (e.g., English, Russian) and can learn programming languages (e.g., C, Java).
Computers operate on binary (zeros and ones) and cannot understand human languages directly.
Historical context: Early programmers manually turned switches corresponding to binary states (0 and 1).
Today's programming demands automatic conversion of high-level languages to machine code through compilers.
Definition 24
High Level Programming Language: Complex constructs/languages like C or Java, where each statement corresponds to many machine instructions and is independent of the processor's ISA.
Compiler: An executable program that converts high-level programming into machine code (sequence of zeros and ones).
Figure 3.1: Illustrates the compilation process where high-level code is transformed into machine code.
Trivia 1: History of Compilers
The original compiler needed a compiler to compile itself, creating a "chicken and egg" conundrum. Early programmers first created simple machine instruction-based compilers and subsequently advanced to high-level language compilers.
Modern development uses cross-compilers, which run on one machine and produce executable code for a different machine with potentially different ISAs.
Definition 25: Cross-Compiler – A program running on system A generating code for system B.
Despite the effectiveness of compilers, certain scenarios necessitate manual embedding of machine instructions in programs for efficiency or functionality.
Compilers face limitations in optimizing machine code due to constraints on algorithm efficiency and lack of awareness of broader code patterns.
Some instructions (added by processor vendors) may not be utilized by generic compilers, necessitating manual inclusion by system programmers.
Definition 26
Assembly Language: A low-level programming language with statements that each correspond to a single machine instruction, easing programmer's burden of memorizing binary sequences.
Assembly languages have a structured format consisting of instructions and operands, generally enabling the embedding of assembly within high-level languages and maintaining close control over hardware.
Definition 27
Assembler: An executable program that converts assembly language code into machine code.
Examples of Assembly Language Use
Example 20: High-performance 3D games require speed optimization, leading programmers to write assembly code for performance gains.
Example 21: In high-performance atom structure computing, assembly code writing significantly accelerated execution speed on supercomputers, as demonstrated by various studies.
3.1.2 Hardware Designer’s Perspective
Hardware designers focus on designing processors that implement instructions following the ISA effectively, considering efficiency in area, power, and complexity.
They depend on the assembly language for an understanding of what to build and how to translate instructions into hardware designs.
3.2 The Basics of Assembly Language
3.2.1 Machine Model
Revisiting the Harvard and Von Neumann architecture, assembly languages do not distinguish instruction and data memories, following an abstract Von Neumann machine model enhanced with registers.
The CPU reads and executes program instructions stored in main memory, and the Program Counter (PC) keeps track of the currently executing instruction.
CPU Components
Registers: Store input operands; most CPUs have fewer than 64 registers, with operations potentially sourcing from either registers or memory.
The CPU coordinates memory transfers, performs arithmetic and logical computations, and manages external I/O devices.
3.2.2 View of Memory
Memory, as an array of bytes, is indexed uniquely by addresses starting from 0.
Different data types in programming languages necessitate multimemory representations, implying that multibyte types require specified byte allocations.
Little Endian and Big Endian Representations
Little Endian: Stores least significant byte first.
Big Endian: Stores most significant byte first.
Example 22: With integer 0x87654321, the big and little endian representations would differ based on which byte is physically stored first in memory locations.
ARM processors can operate in bi-endian mode, while x86 traditionally uses little endian, and others like IBM POWER use big endian formats.
Arrays Representation
Arrays are sequences of memory locations, stored contiguously in one dimension, with an index mapping from multi-dimensional arrays to a single-dimensional structure.
Definition 28
Row Major Representation: Storing arrays row-wise in memory.
Column Major Representation: Storing arrays column-wise in memory.
3.2.3 Assembly Language Syntax
The syntax of assembly language depends on the assembler, with GNU assembler syntax covered.
An assembly file, a regular text file, typically has a
.sfile extension, which can be generated from C programs using a command-line interface integrated with the GCC.