Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:multiasm:papc:chapter_6_8 [2025/11/25 13:48] – [Callig Linux system functions] ktokarzen:multiasm:papc:chapter_6_8 [2026/02/27 01:48] (current) – [Callig Windows system functions] jtokarz
Line 4: Line 4:
 The name depends on the programming language. In assembler, the common name for a separate fragment of the code called from another part is a procedure. The procedure can be separately tested and used multiple times in the same program or in other projects. Using procedures makes the code easier to manage and reusable, increasing the overall efficiency of software creation.  The name depends on the programming language. In assembler, the common name for a separate fragment of the code called from another part is a procedure. The procedure can be separately tested and used multiple times in the same program or in other projects. Using procedures makes the code easier to manage and reusable, increasing the overall efficiency of software creation. 
  
-Procedures can be defined using a pair of directives. The **PROC** directive is used at the beginning of the procedure, and the **ENDP** directive is used at the end. The **PROC** directive can automatically:+Procedures can be defined using a pair of directives. The **PROC** directive is used at the beginning of the procedure, and the **ENDP** directive is used at the end. Up to 32-bit version the **PROC** directive can automatically:
   * Preserve the contents of the registers whose values should not change, but are needed for use in the procedure.   * Preserve the contents of the registers whose values should not change, but are needed for use in the procedure.
   * Set up local variables on the stack.   * Set up local variables on the stack.
   * Set up parameters placed on the stack.   * Set up parameters placed on the stack.
   * Adjust the stack when the procedure ends.   * Adjust the stack when the procedure ends.
-With the use of additional directives, it is possible to provide information about stack utilisation for stack unwinding. 
  
-Procedures can have parameters. In general, parameters can be passed through the stack, registers, common memory or a combination of these. In different operating systems, the rules of passing parameters differ. In 64-bit Windows, the fast call calling convention is used. In this convention, the first four parameters are passed through registers, and each subsequent parameter is passed through the stack. If the parameters are integers, they are passed through general-purpose registers. If parameters are floating-point numbers, they are passed through XMM registers as scalars. If the procedure plays the role of a function, it returns the resulting value. Integers are returned through the accumulator (RAX), and floating-point values are returned through XMM0. Parameters passing in Windows x64 ABI is summarised in a table {{ref>masmparampass}}.+Since the parameter passing method has changed in 64-bit operating systems, the **PROC** directive calculates the addresses of local variables and arguments on the stack properly, but if we want to use the stack for argument passing, we need to put parameters on the stack manually before a procedure call. With the use of additional directives, it is possible to provide information about stack utilisation for stack unwinding. 
 + 
 +Procedures can have parameters. In general, parameters can be passed through the stack, registers, common memory or a combination of these. In different operating systems, the rules of passing parameters differ.  
 + 
 +**Windows Application Binary Interface.**\\ 
 +In 64-bit Windows, the fast call calling convention is used. In this convention, the first four parameters are passed through registers, and each subsequent parameter is passed through the stack. If the parameters are integers, they are passed through general-purpose registers. If parameters are floating-point numbers, they are passed through XMM registers as scalars. If the procedure plays the role of a function, it returns the resulting value. Integers are returned through the accumulator (RAX), and floating-point values are returned through XMM0. Parameters passing in Windows x64 ABI is summarised in a table {{ref>masmparampass}}.
 <table masmparampass> <table masmparampass>
 <caption>Parameter passing in 64-bit Windows calling convention</caption> <caption>Parameter passing in 64-bit Windows calling convention</caption>
Line 43: Line 47:
  
 The Microsoft Windows x64 calling convention requires that even when the parameters are passed through registers, a 32-byte space for them should be reserved on the stack. It is referred to as a shadow space or home space. The shadow space size can be increased to store local variables of the procedure. Why does the x64 calling convention require the shadow space to be explained in the Microsoft blog article((https://devblogs.microsoft.com/oldnewthing/20160623-00/?p=93735)).\\ The Microsoft Windows x64 calling convention requires that even when the parameters are passed through registers, a 32-byte space for them should be reserved on the stack. It is referred to as a shadow space or home space. The shadow space size can be increased to store local variables of the procedure. Why does the x64 calling convention require the shadow space to be explained in the Microsoft blog article((https://devblogs.microsoft.com/oldnewthing/20160623-00/?p=93735)).\\
 +Some registers are considered non-volatile. It means that they must be saved and restored by a function that uses them. They are RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15, and XMM6-XMM15.\\
 +
 Another requirement is that the stack must be aligned to the 16-byte boundaries. This is done for the performance, because data transfer between the processor and memory at aligned addresses can be done with faster versions of instructions (**MOVAPD** instead of **MOVUPD**). Note that the returning address, which is pushed on the stack automatically when the procedure is called, is 8 bytes long, so even without the shadow space, the stack pointer adjustment is required. Our simple AddProc function doesn't adjust the stack because it doesn't call any function which needs the stack to be aligned. If we decide to call a system function, we must align the stack before making a call. Before modification of the stack pointer, we must preserve its content and restore it before returning. Another requirement is that the stack must be aligned to the 16-byte boundaries. This is done for the performance, because data transfer between the processor and memory at aligned addresses can be done with faster versions of instructions (**MOVAPD** instead of **MOVUPD**). Note that the returning address, which is pushed on the stack automatically when the procedure is called, is 8 bytes long, so even without the shadow space, the stack pointer adjustment is required. Our simple AddProc function doesn't adjust the stack because it doesn't call any function which needs the stack to be aligned. If we decide to call a system function, we must align the stack before making a call. Before modification of the stack pointer, we must preserve its content and restore it before returning.
 <code asm> <code asm>
Line 59: Line 65:
 Certainly, these rules are to be used if there is a need to call a system function or to maintain compatibility with a high-level compiler. If the procedure is written in pure assembly and called from an assembly program, it is the programmer's decision whether they want to follow these rules.\\ Certainly, these rules are to be used if there is a need to call a system function or to maintain compatibility with a high-level compiler. If the procedure is written in pure assembly and called from an assembly program, it is the programmer's decision whether they want to follow these rules.\\
 The rules of passing parameters, stack and registers use, and data storage layout in 64-bit Microsoft Windows are described in the document about x64 Application Binary Interface (ABI)((https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions?view=msvc-170)).\\ The rules of passing parameters, stack and registers use, and data storage layout in 64-bit Microsoft Windows are described in the document about x64 Application Binary Interface (ABI)((https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions?view=msvc-170)).\\
 +**Linux System V Application Binary Interface.**\\
 In the Linux x64 Calling Convention, the first six arguments of type integer/pointers are passed in registers and subsequent arguments through the stack. For the floating point arguments, the first eight are passed in XMM registers, and the subsequent ones through the stack. Parameters passing in Linux is summarised in a table {{ref>linuxparampass}}. In the Linux x64 Calling Convention, the first six arguments of type integer/pointers are passed in registers and subsequent arguments through the stack. For the floating point arguments, the first eight are passed in XMM registers, and the subsequent ones through the stack. Parameters passing in Linux is summarised in a table {{ref>linuxparampass}}.
 <table linuxparampass> <table linuxparampass>
Line 73: Line 80:
 | subsequent | stack | stack |  | subsequent | stack | stack | 
 </table> </table>
 +The non-volatile registers are RBX, RBP, R12, R13, R14, and R15. They should be saved and restored by a function that uses them.
  
 ===== Calling the system functions ===== ===== Calling the system functions =====
-The operating systems offer a set of functions which help write an application. These functions include reading characters and text from standard input, usually the keyboard, displaying characters or text on standard output, usually the monitor, handling files, data streams and many others. In previous generations of operating systems, the software interrupt mechanism was used. In Microsoft DOS, it was **int 21h** while in 32-bit versions of Linux it was **int 80h**. Calling the system function required preparing the arguments in scratch registers and signalling the software interrupt.+The operating systems offer a set of functions which help write an application. These functions include reading characters and text from standard input, usually the keyboard, displaying characters or text on standard output, usually the monitor, handling files, data streams and many others. In previous generations of operating systems, the software interrupt mechanism was used. In Microsoft DOS, it was **int 21h** while in 32-bit versions of Linux it was **int 80h** (or in the C-style hex notation int 0x80). Calling the system function required preparing the arguments in scratch registers and signalling the software interrupt.
 <note> <note>
 You can still find many examples using the software interrupt system call on the Internet. In Linux, they should work properly, although they are slower than the new method. In 64-bit Windows, the **int 21** method is no longer supported. You can still find many examples using the software interrupt system call on the Internet. In Linux, they should work properly, although they are slower than the new method. In 64-bit Windows, the **int 21** method is no longer supported.
Line 107: Line 115:
 ; after the function call is aligned to mod(8) ; after the function call is aligned to mod(8)
 ; the Windows requires the shadow space on the stack ; the Windows requires the shadow space on the stack
-push rbp  ; push rpb to the stack +    push  rbp        ; push rpb to the stack 
-mov  rbp, rsp  ; store rsp to rbp +    mov   rbp, rsp   ; store rsp to rbp 
-sub  rsp, 48 ; shadow space (32 bytes) and stack alignment (additional 8 bytes)+    sub   rsp, 48    ; shadow space (32 bytes) and stack alignment (additional  
 +                     ; 8 bytes)
  
 ; we need the handle of the console window ; we need the handle of the console window
-mov rcx, STD_OUTPUT_HANDLE +    mov   rcx, STD_OUTPUT_HANDLE 
-call GetStdHandle +    call  GetStdHandle 
-mov stdout_handle, rax+    mov   stdout_handle, rax
  
 ; display the text in the console window ; display the text in the console window
-mov rcx, stdout_handle +    mov   rcx, stdout_handle 
-mov rdx, offset hello_msg +    mov   rdx, offset hello_msg 
-mov r8,  sizeof hello_msg +    mov   r8,  sizeof hello_msg 
-mov r9,  dummy +    mov   r9,  dummy 
-call     WriteConsoleA+    call  WriteConsoleA
  
 ; restore the stack pointer and rbp ; restore the stack pointer and rbp
-mov rsp, rbp +    mov   rsp, rbp 
-pop rbp+    pop   rbp
  
 ; return from the function ; return from the function
-ret+    ret
 MyAssemblerFunction ENDP MyAssemblerFunction ENDP
 END END
Line 134: Line 143:
  
 ===== Callig Linux system functions ===== ===== Callig Linux system functions =====
-The Linux operating system still supports the traditional calling of system functions using software interrupts. It is based on the **int 80h** (or in the C style hex notation int 0x80) interrupt, which recognises the number of the function in the EAX register and up to six arguments in EBX, ECX, EDX, ESI, EDI, and EBP. +The Linux operating system still supports the traditional calling of system functions using software interrupts. It is based on the **int 0x80** interrupt, which recognises the number of the function in the EAX register and up to six arguments in EBX, ECX, EDX, ESI, EDI, and EBP. 
 The example of the Hello World program in Linux interrupt-based system call is shown in the following code. The example of the Hello World program in Linux interrupt-based system call is shown in the following code.
  
Line 153: Line 162:
  
 section    .data section    .data
-msg  db    "Hello World!"+msg  db    "Hello World!", 10
 len  equ   $ - msg len  equ   $ - msg
 </code> </code>
  
-Modern processors have new instructions especially designed for calling system functions. They are supported in the Linux operating system. The **syscall** instruction doesn't use the interrupt mechanism. It uses registers only to provide the address of the function, store the return address and flags register, and load the instruction pointer. This makes the **syscall** instruction execution significantly faster than **int 80h**, and is the preferred mechanism for system calls in 64-bit Linux systems. The RIP is stored in RCX, and RFLAGS is stored in R11. The RIP is loaded with the content of the special register IA32_LSTAR MSR, which is an element of Architectural Model-Specific Registers, implemented starting from certain models of 32-bit processors. The Linux system sets this register, and the programmer selects the function using the RAX register, as in the previous model of system calls.+===== Syscall mechanism ===== 
 +Modern processors have new instruction especially designed for calling system functions.  
 +The **syscall** instruction doesn't use the interrupt mechanism, nor the stack for storing the returning address. It uses registers only to provide the address of the function, store the return address and flags register, and load the instruction pointer. The RIP is stored in RCX, and RFLAGS is stored in R11. The RIP is loaded with the content of the special register IA32_LSTAR MSR, which is an element of Architectural Model-Specific Registers, implemented starting from certain models of 32-bit processors. This makes the **syscall** instruction execution significantly faster than other mechanisms. 
 + 
 +The **syscall** instruction is supported in both Windows and Linux operating systems. It replaces Linux **int 80h**, and is the preferred mechanism for system calls in the 64-bit version of this system. The Linux system sets this register, and the programmer selects the function using the RAX register, as in the previous model of system calls.
  
 <code asm> <code asm>
Line 178: Line 191:
  
 msg: db    "Hello World!", 10 msg: db    "Hello World!", 10
-len  equ   $ - hello_world+len  equ   $ - msg
 </code> </code>
 +
 +In Windows, low-level system functions are gathered in the ntdll.dll library. While using a high-level Windows API function, it results in calling a corresponding syscall. Although it is possible to call the low-level system function with syscall, API calls are preferred for user software.
en/multiasm/papc/chapter_6_8.1764071291.txt.gz · Last modified: by ktokarz
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0