- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是一个初学者@coding,这是我在堆栈溢出上的第一个问题,尽管你的一些很好的答案已经让我取得了一些进展..
尝试此操作时 assembler-tutorial运行程序后我遇到段错误。我尝试注释掉每一行,并注意到当我在第 30 行“调用 printString”时程序崩溃了。
当我尝试使用 gdb 进行调试时(哎呀,我真的不知道我在做什么..),我在 lenString 调用中的函数“iterateChar”中收到错误。 (来 self 的函数文件 - baseOperators.asm - 第 50 行)
我怀疑,不知何故我弄乱了 eax 寄存器中的信息,但我不知道为什么,发生了什么以及如何解决这个问题。我的代码看起来与 asmtutor.com 上的教程 16 中的代码非常相似 - 我对它进行了 c&p 编辑,并且无论出于何种原因,它都有效。请帮忙。
(我使用“$ nasm -f elf assemblerTutorial.asm”+“$ ld -m elf_i386 assemblerTutorial.o -o assemblerTutorial)进行编译
;------------------------------------------
; my Assembler learning Environment
;%include "calculate.asm"
%include "baseOperators.asm"
%include "print.asm"
SECTION .text
global _start
_start:
pop ecx
mov edx, 0
argumentsLoop:
cmp ecx, 0h
jz argumentsEnd
pop eax
call atoi
add edx, eax
dec ecx
jmp argumentsLoop
argumentsEnd:
mov eax, edx
call printString
call breakLine
call quit
我的baseOperators.asm:
;------------------------------------------
; int atoi(Integer number)
; Ascii to integer function (atoi)
atoi:
push ebx ; preserve ebx on the stack to be restored after function runs
push ecx ; preserve ecx on the stack to be restored after function runs
push edx ; preserve edx on the stack to be restored after function runs
push esi ; preserve esi on the stack to be restored after function runs
mov esi, eax ; move pointer in eax into esi (our number to convert)
mov eax, 0 ; initialise eax with decimal value 0
mov ecx, 0 ; initialise ecx with decimal value 0
.conversionLoop:
xor ebx, ebx ; resets both lower and uppper bytes of ebx to be 0
mov bl, [esi+ecx] ; move a single byte into ebx register's lower half
cmp bl, 48 ; compare ebx register's lower half value against ascii value 48 (char value 0)
jl .conversionEnd ; jump if less than to label finished
cmp bl, 57 ; compare ebx register's lower half value against ascii value 57 (char value 9)
jg .conversionEnd ; jump if greater than to label finished
cmp bl, 10 ; compare ebx register's lower half value against ascii value 10 (linefeed character)
je .conversionEnd ; jump if equal to label finished
cmp bl, 0 ; compare ebx register's lower half value against decimal value 0 (end of string)
jz .conversionEnd ; jump if zero to label finished
sub bl, 48 ; convert ebx register's lower half to decimal representation of ascii value
add eax, ebx ; add ebx to our interger value in eax
mov ebx, 10 ; move decimal value 10 into ebx
mul ebx ; multiply eax by ebx to get place value
inc ecx ; increment ecx (our counter register)
jmp .conversionLoop ; continue multiply loop
.conversionEnd:
mov ebx, 10 ; move decimal value 10 into ebx
div ebx ; divide eax by value in ebx (in this case 10)
pop esi ; restore esi from the value we pushed onto the stack at the start
pop edx ; restore edx from the value we pushed onto the stack at the start
pop ecx ; restore ecx from the value we pushed onto the stack at the start
pop ebx ; restore ebx from the value we pushed onto the stack at the start
ret
;------------------------------------------
; int lenString(String message)
; String length calculation function
lenString:
push ebx
mov ebx, eax
iterateChar:
cmp byte [eax], 0
jz finalize
inc eax
jmp iterateChar
finalize:
sub eax, ebx
pop ebx
ret
;------------------------------------------
; void breakLine()
; Break a line - linefeed
breakLine:
push eax ; push eax on the stack
mov eax, 0x0a ; move linefeed into eax - 0x0a = 0Ah
push eax ; linefeed on stack to get adress
mov eax, esp ; move adress of current pointer into eax
call printString
pop eax
pop eax
ret ; return
;------------------------------------------
; void exit()
; Exit program and restore resources
quit:
mov eax, 1 ; invoke SYS_EXIT (kernel opcode 1)
mov ebx, 0 ; return 0 status on exit - 'No Errors'
int 0x80 ; 0x80=80h
ret
以及 print.asm 中的打印函数:
;------------------------------------------
; void printInteger (Integer number)
; Integer printing function (itoa)
printInteger:
push eax ; preserve eax on the stack to be restored after function runs
push ecx ; preserve ecx on the stack to be restored after function runs
push edx ; preserve edx on the stack to be restored after function runs
push esi ; preserve esi on the stack to be restored after function runs
mov ecx, 0 ; counter of how many bytes we need to print in the end
divideLoop:
inc ecx ; count each byte to print - number of characters
mov edx, 0 ; empty edx
mov esi, 10 ; mov 10 into esi
idiv esi ; divide eax by esi
add edx, 48 ; convert edx to it's ascii representation - edx holds the remainder after a divide instruction
push edx ; push edx (string representation of an intger) onto the stack
cmp eax, 0 ; can the integer be divided anymore?
jnz divideLoop ; jump if not zero to the label divideLoop
printLoop:
dec ecx ; count down each byte that we put on the stack
mov eax, esp ; mov the stack pointer into eax for printing
call printString ; call our string print function
pop eax ; remove last character from the stack to move esp forward
cmp ecx, 0 ; have we printed all bytes we pushed onto the stack?
jnz printLoop ; jump is not zero to the label printLoop
pop esi ; restore esi from the value we pushed onto the stack at the start
pop edx ; restore edx from the value we pushed onto the stack at the start
pop ecx ; restore ecx from the value we pushed onto the stack at the start
pop eax ; restore eax from the value we pushed onto the stack at the start
ret
;------------------------------------------
; void printString(String message)
; String printing function
printString:
push edx
push ecx
push ebx
push eax
call lenString
mov edx, eax ; nbytes - number of bytes to write (len), one for each letter plus the zero terminating byte
pop eax
mov ecx, eax ; buffer - move the memory address of our message string into ecx
mov ebx, 1 ; fd - filedescriptor, write to the STDOUT file
mov eax, 4 ; invoke SYS_WRITE (with fd, buf, nbytes / kernel opcode 4)
int 0x80 ; prozessor interupt 0x80 jump to system call, stack clean, 0x80=80h
pop ebx
pop ecx
pop edx
ret
感谢任何提示,
亲切的问候
最佳答案
如果程序以正常、传统且合法的方式启动,则堆栈上始终已有一个参数:程序本身的路径。因此,第一个 POP (pop ecx
) 至少为 1。如果再有两个参数,该值将为 3。将 ECX 寄存器减 1 或将其与 1 进行比较:
...
argumentsLoop:
cmp ecx, 1h
jz argumentsEnd ; See footnote ¹
...
第一个命令行参数的地址位于堆栈的第三个位置。你必须弹出程序路径的地址:
...
_start:
pop ecx ; Get the arguments count
mov edx, 0
pop eax ; Pop away the program path
...
函数 atoi
将 ASCII 字符串转换为整数。函数printString
顾名思义,只打印字符串,而不打印整数。使用 printInteger
代替:
...
argumentsEnd:
mov eax, edx
call printInteger
...
1 可以在不使用任何参数 (argc = 0) 或使用约定未涵盖的 argv[0] 的情况下启动程序(请参阅 execve(2) )。我写了一个例子来演示它:
get_argv.asm:
SECTION .data
LineFeed dw 10
nullstr db '(null)',0
argcstr db 'argc = '
argcstr1 db '---------------',0
argvstr db 'argv['
argvstr1 db '---------------',0
argvstr2 db '] = ',0
SECTION .text
global _start
_start:
push ebp
mov ebp, esp
mov eax, [ebp + 4] ; argc
mov edi, argcstr1
call EAX_to_DEC ; Convert EAX to a string pointed by EDI
mov esi, argcstr
call PrintString
mov esi, LineFeed
call PrintString
xor ecx, ecx
.J1:
mov eax, ecx
mov edi, argvstr1
call EAX_to_DEC ; Convert EAX to a string pointed by EDI
mov esi, argvstr
call PrintString
mov esi, argvstr2
call PrintString
mov esi, [ebp+8+4*ecx] ; argv[ECX]
call PrintString
test esi, esi
jz .J2
mov esi, LineFeed
call PrintString
add ecx, 1
jmp .J1
.J2:
.exit:
mov esi, LineFeed
call PrintString
mov esp, ebp
pop ebp
mov eax, 1 ; SYS_EXIT
xor ebx, ebx ; Exit code = 0 = no error
int 0x80 ; Call Linux kernel
PrintString: ; ARG: ESI Pointer to ASCIZ string
pusha
test esi, esi
jne .J0
mov esi, nullstr
.J0:
mov eax, 4 ; SYS_WRITE
mov ebx, 1 ; STDOUT
mov ecx, esi
xor edx, edx ; Count of bytes to send
.J1:
cmp byte [esi], 0 ; Look for the terminating null
je .J2
add edx, 1
add esi, 1
jmp .J1
.J2:
int 0x80 ; Call Linux kernel
popa
ret
EAX_to_DEC: ; ARG: EAX integer, EDI pointer to string buffer
push ebx
push ecx
push edx
mov ebx, 10 ; Divisor = 10
xor ecx, ecx ; ECX=0 (digit counter)
.J1: ; First Loop: store the remainders
xor edx, edx ; Don't forget it!
div ebx ; EDX:EAX / EBX = EAX remainder EDX
push dx ; Push the digit in DL (LIFO)
add cl, 1 ; = inc cl (digit counter)
or eax, eax ; AX == 0?
jnz .J1 ; No: once more
mov ebx, ecx ; Store count of digits
.J2: ; Second loop: load the remainders in reversed order
pop ax ; get back pushed digits
or al, 00110000b ; to ASCII
mov [edi], al ; Store AL to [EDI] (EDI is a pointer to a buffer)
add edi, 1 ; = inc edi
loop .J2 ; until there are no digits left
mov byte [edi], 0 ; ASCIIZ terminator (0)
mov eax, ebx ; Restore Count of digits
pop edx
pop ecx
pop ebx
ret ; RET: EAX length of string (w/o last null)
start_get_argv.c:
#include <stdio.h>
#include <unistd.h>
int main ( int argc, char *argv[] )
{
char* asmprog = "./get_argv";
puts ("execute me\n");
printf ("argc = %d\n",argc);
for (int i=0; i <= argc; ++i)
{
printf ("argv[%d]=%s\n",i,argv[i]);
}
printf ("\nexecve %s\n\n",asmprog);
fflush (0);
execve (asmprog, NULL, NULL);
return 0;
}
在同一目录中构建这两个文件并运行 ./start_get_argv。调用的 ./get_argv 将报告 argc = 0 和 argv[0] = (null)。空指针意味着“数组末尾”。处理这种情况很简单:如果 argc 小于或等于 1,则退出:
...
argumentsLoop:
cmp ecx, 1h
jbe argumentsEnd
...
关于assembly - 入门教程 : Assembler, 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48227295/
我已经使用 vue-cli 两个星期了,直到今天一切正常。我在本地建立这个项目。 https://drive.google.com/open?id=0BwGw1zyyKjW7S3RYWXRaX24tQ
您好,我正在尝试使用 python 库 pytesseract 从图像中提取文本。请找到代码: from PIL import Image from pytesseract import image_
我的错误 /usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss mismatches non-TLS reference
我已经训练了一个模型,我正在尝试使用 predict函数但它返回以下错误。 Error in contrasts<-(*tmp*, value = contr.funs[1 + isOF[nn]])
根据Microsoft DataConnectors的信息我想通过 this ODBC driver 创建一个从 PowerBi 到 PostgreSQL 的连接器使用直接查询。我重用了 Micros
我已经为 SoundManagement 创建了一个包,其中有一个扩展 MediaPlayer 的类。我希望全局控制这个变量。这是我的代码: package soundmanagement; impo
我在Heroku上部署了一个应用程序。我正在使用免费服务。 我经常收到以下错误消息。 PG::Error: ERROR: out of memory 如果刷新浏览器,就可以了。但是随后,它又随机发生
我正在运行 LAMP 服务器,这个 .htaccess 给我一个 500 错误。其作用是过滤关键字并重定向到相应的域名。 Options +FollowSymLinks RewriteEngine
我有两个驱动器 A 和 B。使用 python 脚本,我在“A”驱动器中创建一些文件,并运行 powerscript,该脚本以 1 秒的间隔将驱动器 A 中的所有文件复制到驱动器 B。 我在 powe
下面的函数一直返回这个错误信息。我认为可能是 double_precision 字段类型导致了这种情况,我尝试使用 CAST,但要么不是这样,要么我没有做对...帮助? 这是错误: ERROR: i
这个问题已经有答案了: Syntax error due to using a reserved word as a table or column name in MySQL (1 个回答) 已关闭
我的数据库有这个小问题。 我创建了一个表“articoli”,其中包含商品的品牌、型号和价格。 每篇文章都由一个 id (ID_ARTICOLO)` 定义,它是一个自动递增字段。 好吧,现在当我尝试插
我是新来的。我目前正在 DeVry 在线学习中级 C++ 编程。我们正在使用 C++ Primer Plus 这本书,到目前为止我一直做得很好。我的老师最近向我们扔了一个曲线球。我目前的任务是这样的:
这个问题在这里已经有了答案: What is an undefined reference/unresolved external symbol error and how do I fix it?
我的网站中有一段代码有问题;此错误仅发生在 Internet Explorer 7 中。 我没有在这里发布我所有的 HTML/CSS 标记,而是发布了网站的一个版本 here . 如您所见,我在列中有
如果尝试在 USB 设备上构建 node.js 应用程序时在我的树莓派上使用 npm 时遇到一些问题。 package.json 看起来像这样: { "name" : "node-todo",
在 Python 中,您有 None单例,在某些情况下表现得很奇怪: >>> a = None >>> type(a) >>> isinstance(a,None) Traceback (most
这是我的 build.gradle (Module:app) 文件: apply plugin: 'com.android.application' android { compileSdkV
我是 android 的新手,我的项目刚才编译和运行正常,但在我尝试实现抽屉导航后,它给了我这个错误 FAILURE: Build failed with an exception. What wen
谁能解释一下?我想我正在做一些非常愚蠢的事情,并且急切地等待着启蒙。 我得到这个输出: phpversion() == 7.2.25-1+0~20191128.32+debian8~1.gbp108
我是一名优秀的程序员,十分优秀!