【问题标题】:Input incorrect Assembly x86 NASM输入不正确的程序集 x86 NASM
【发布时间】:2014-03-26 03:40:40
【问题描述】:

我已经看了好几个小时了,不明白为什么在我第二次输入后,我从第一次输入中存储的字符串发生了变化。

当我像这样运行示例运行时:

请输入id:12

请输入姓名:周杰伦

当我为标准输入和输出运行这部分代码时,gdb 显示第一次读取后 id1Buf 的值为“12\n”。然后它提示输入名称,所以当我输入 jay 时,id1Buf 值由于某种原因更改为“12\njay”。想不通,如果有人能帮忙就好了。

SECTION .text                               ;.text section

global _start                               ;start section

_start:                                     ;start
    main:     
        ;;write out
        mov eax, SYSCALL_WRITE              ;write function
        mov ebx, STDOUT                     ;write value
        mov ecx, id                         ;address of message
        mov edx, lenid                      ;length of message
        int 80h                             ;interrupt

        ;;read user input
        mov eax, SYSCALL_READ               ;read function
        mov ebx, STDIN                      ;read in value
        mov ecx, id1Buf                     ;store read value in id1Buf
        mov edx, IDBUFLEN                   ;length of idbuf
        int 80h                             ;interrupt

        ;;write out
        mov eax, SYSCALL_WRITE              ;write function
        mov ebx, STDOUT                     ;write value
        mov ecx, name                       ;address of message
        mov edx, lenname                    ;length of message
        int 80h                             ;interrupt

        ;;read user input
        mov eax, SYSCALL_READ               ;read function
        mov ebx, STDIN                      ;read in value
        mov ecx, name1Buf                   ;store read value in name1Buf
        mov edx, NAMEBUFLEN                 ;length of namebuf
        int 80h                             ;interrupt

        mov [name1readlen], eax             ;store length of name

这是其他一些代码供参考。

;;constants 
%define STDIN 0                             ;read function
%define STDOUT 1                            ;write function
%define STDERR 2                            ;error function
%define SYSCALL_EXIT 1                      ;exit 
%define SYSCALL_READ 3                      ;read
%define SYSCALL_WRITE 4                     ;write
%define IDBUFLEN 3                          ;length of id buffer
%define NAMEBUFLEN 500                      ;length of name buffer

;;given data
SECTION .data
    id db "Please enter the id: "           ;prompt for id
    lenid equ $-id                          ;length of id prompt

    name db "Please enter the name: "       ;prompt for name
    lenname equ $-name                      ;length of name

    idlabel db "ID:    "                    ;used for printing end data
    lenidlabel equ $-idlabel                ;length of id label

    namelabel db "NAME: "                   ;used for printing end data
    lennamelabel equ $-namelabel            ;length of name label

    printline db "", 10                     ;new line character


;;unintialized data
SECTION .bss
    id1Buf:        resb IDBUFLEN             ;buffer for id 1
    name1Buf:      resb NAMEBUFLEN           ;buffer for name 1

【问题讨论】:

  • 告诉我当您将 resb IDBUFLEN 更改为 4 或 5 而不是 3 时会发生什么,然后还考虑使用 null 终止存储在 id1Buf 中的字符串。
  • @alvonellos 当我更改为 4 时 id1Buf 变为 "12\n\000jay\n" 如果我​​为空终止它 id1Buf 变为 "12\000\000jay\n"
  • 由于某种偏移条件,它们一起运行,尝试使用 equ 而不是 %define 作为该常量并告诉我会发生什么。
  • @alvonellos 对不起,我是这个语言的新手,你把它放在 .data 部分下吗?你会怎么做IDBUFLEN equ 2
  • 你的缓冲区是连续的,你希望它做什么?

标签: assembly io x86 gdb nasm


【解决方案1】:

啊,让我把它作为一个“答案”(虽然我不确定它是一个)。你看到的是预期的行为。你有一个三字节的缓冲区,你用'1'、'2'和'\n'填充它。紧接着你有另一个(更长的)缓冲区,你可以在其中放置“J”、“a”、“y”和“\n”。

请注意,sys_read 以换行符 (\n) 结束您的输入,而不是零。在“输入”被击中之前它不会返回。 (这适用于 STDIN - 其他文件不同)如果讨厌的用户输入“12345(enter)”,你会遇到更大的问题,第一个缓冲区将获得 '1'、'2'、'3' - 它不会溢出 - 但在“名称”提示之后,它不会暂停,而是将 '4'、'5'、'\n' 放入名称缓冲区。解决方案是确保您有换行符!

; your sys_read
int 80h
push eax ; probably want to save the original length
checkLF:
cmp byte [ecx + eax - 1], LF
jz goodread
mov ecx, dummybuf ; to be thrown away
mov edx, 1
mov ebx, STDIN ; still in there, probably
mov eax, SYSCALL_READ
int 80h
jmp checkLF
goodread:
pop eax  ; get original length back

您可能希望以零结尾的字符串。 (也许也应该保存原始的ecxsys_write 不期望以零结尾的字符串,但我们可以找到长度并将其放入edx

mov ecx, buffer ; maybe a parameter?
xor edx, edx
getlen:
cmp byte [ecx + edx], 0
jz gotlen
inc edx
jmp getlen
gotlen:
; rest of your sys_read

您在评论中询问如何处理多个输入。我会考虑一个指向名称字符串的指针数组和一个指向 id 字符串的指针数组。可能是一个长度数组(对于每个?)。迈出一小步...

idarray dd id1buf, id2buf, id3buf, id4buf...
namearray dd name1buf, name2buf, name3buf...
; ...
mov edi, which customer we want
mov esi, [namearray + edi * 4]
; send it off for manipulating
inc edi ; next customer
; find his id?
mov ecx, [idarray + edi * 4]
; send it off to print

大概是这样的吧?

【讨论】:

  • 非常感谢,数组的最后一部分帮助很大,我现在一切正常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-13
  • 2022-01-01
  • 2015-09-20
  • 1970-01-01
  • 2015-09-22
  • 2011-12-22
  • 1970-01-01
相关资源
最近更新 更多