我一直在阅读div和mul组装操作,我决定通过在C中编写一个简单的程序来实现它们:
#include <stdlib.h>
#include <stdio.h>
int main()
{
size_t i = 9;
size_t j = i / 5;
printf("%zu\n",j);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后生成汇编语言代码:
gcc -S division.c -O0 -masm=intel
Run Code Online (Sandbox Code Playgroud)
但是看生成的division.s文件,它不包含任何div操作!相反,它通过位移和魔术数字来做某种黑魔法.这是一个计算代码片段i/5:
mov rax, QWORD PTR [rbp-16] ; Move i (=9) to RAX
movabs rdx, -3689348814741910323 ; Move some magic number to RDX (?)
mul rdx ; Multiply 9 by magic number
mov rax, rdx ; Take only the upper 64 bits of the …Run Code Online (Sandbox Code Playgroud) 以下链接解释了UNIX(BSD风格)和Linux的x86-32系统调用约定:
但是UNIX和Linux上的x86-64系统调用约定是什么?
是否有可能通过使用纯位加法,减法除以10的无符号整数,也许繁衍?使用资源非常有限且速度慢的处理器.
假设我在寄存器中有一个整数,我该如何打印?你能展示一个简单的示例代码吗?
我已经知道如何打印一个字符串,如"你好,世界".
我正在Linux上开发.
当我在16位汇编中添加两个值时,将结果打印到控制台的最佳方法是什么?
目前我有这个代码:
;;---CODE START---;;
mov ax, 1 ;put 1 into ax
add ax, 2 ; add 2 to ax current value
mov ah,2 ; 2 is the function number of output char in the DOS Services.
mov dl, ax ; DL takes the value.
int 21h ; calls DOS Services
mov ah,4Ch ; 4Ch is the function number for exit program in DOS Services.
int 21h ; function 4Ch doesn't care about anything in the registers.
;;---CODE END---;;
Run Code Online (Sandbox Code Playgroud)
我认为dl值应该是ASCII码,但我不确定如何在添加到ASCII后转换ax值.
这需要在纯汇编中完成(即没有库或调用C).
我理解问题的本质:需要将整数除以10,将一位数的余数转换为ASCII,然后输出,然后用商重复该过程.
但由于某种原因,它只是不起作用.我在x86上使用NASM.
这是我现在所拥有的(不输出任何内容,但也不会抛出任何汇编错误):
; integer to output is stored in eax
mov ecx, 10 ; for base 10
loop:
div ecx ;EAX contains the quotient, EDX the remainder
; Do something to EDX to convert it to ASCII, not sure if this is correct
add edx, '0'
push eax ;We'll be playing with EAX to output EDX, save EAX to the stack
mov eax, 4 ; sys_write
mov ebx, 1 ; to STDOUT
mov ecx, edx
mov edx, 1 …Run Code Online (Sandbox Code Playgroud) 我试图在linux上的nasm程序集中打印单个数字整数.我目前编写的内容很好,但没有任何内容写入屏幕.任何人都可以向我解释我在这里做错了什么吗?
section .text
global _start
_start:
mov ecx, 1 ; stores 1 in rcx
add edx, ecx ; stores ecx in edx
add edx, 30h ; gets the ascii value in edx
mov ecx, edx ; ascii value is now in ecx
jmp write ; jumps to write
write:
mov eax, ecx ; moves ecx to eax for writing
mov eax, 4 ; sys call for write
mov ebx, 1 ; stdout
int 80h ; call kernel
mov eax,1 ; …Run Code Online (Sandbox Code Playgroud) 所以我正在学习使用NASM语法的x86 Linux程序集(哦,上帝,不是这个,你们都在考虑).我正在尝试创建一个子程序,只需将EAX中的值打印到stdout即可.代码运行并退出而没有错误,但没有打印.我无法弄清楚为什么.首先,这是我正在处理的文件:
segment .bss
to_print: resd 1
segment .text
global print_eax_val
print_eax_val: ; (top)
push dword ebx ;Stack: edx
push dword ecx ; ecx
push dword edx ; ebx
; (bot)
mov ecx,eax ;ecx = eax
mov [to_print],ecx ;to_print = ecx
mov eax, 4 ;sys_write
mov ebx, 1 ;to stdout
add ecx, 47 ;add 47 for ASCII numbers
mov edx, 2 ;double word = 2 bytes
int 0x80
mov eax, [to_print] ;eax = original val
pop edx ;pop …Run Code Online (Sandbox Code Playgroud) 在这里,我尝试了一些方法来打印 10 到 0 的十进制数字emu8086。
.MODEL SMALL
.STACK 100H
.DATA
NUM DB 58D
.CODE
MAIN PROC
MOV AX,@DATA
MOV DS,AX
START:
CMP NUM,48D
JGE PRINT
JMP END_
PRINT:
MOV AH,2
MOV DL,NUM
INT 21H
DEC NUM
JMP START
END_:
MOV AH,4CH
MAIN ENDP
END MAIN
Run Code Online (Sandbox Code Playgroud)
它在打印 9 到 0 时工作得很好,但它不是打印 10 而是打印asciivalue 的字符10d。我是 .so 的新手,assembly language如何打印 0 到 100 个十进制数字?
我是装配新手,并希望首先尝试直观地了解如何将字符串打印到终端上,而无需通过操作系统抽象(Linux或OSX).
tl; dr如何在OSX上使用NASM在x86-64程序集中写入stdout(打印到终端),尽可能最低级别(即没有系统调用)?BareMetal OS如何做到这一点?
大多数示例显示类似这样:
global start
section .text
start:
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, 13
syscall
mov eax, 60
xor rdi, rdi
syscall
message:
db "Hello world", 10
Run Code Online (Sandbox Code Playgroud)
在那里,他们syscall用来打印依赖于操作系统的字符串.我不是在寻找那个,而是为了如何在最低级别直接将字符串写入stdout.
有这个exokernel项目,BareMetal OS,我认为这样做.虽然因为我不熟悉集会,但我还不知道他们是如何做到这一点的.从它看来,两个重要的文件是:
打印的相关代码似乎是这个(从这两个文件中提取):
;
; Display text in terminal.
;
; IN: RSI = message location (zero-terminated string)
; OUT: All registers preserved
;
os_output:
push rcx
call os_string_length
call os_output_chars …Run Code Online (Sandbox Code Playgroud)