2017-11-08 14 views
0

저는 꽤 혼란스럽고 한 블록 맞았습니다. 내 수업 과제는 다음과 같은 일을합니다. 입력조립 및 버퍼 방법

  1. 인사 사용자
  2. 프롬프트
  3. 변환 된 문자열을 사용자에게 모두 대문자
  4. 디스플레이 메시지에
  5. 변환 문자열

나는 1과 2에는 문제가 없으며, 필요할 때 소문자를 대문자로 변환하는 루프를 알아낼 수 있습니다.

cmp $96, %ah 
jg Subtract 
call Loop 

Subtract: 
    sub $32, %ah 
    mov %ah, back to the array 
    ret 

이것이 최선의 방법은 아닐지 모르지만 일단이 배열과 버퍼를 알아 내면 알아낼 수 있습니다. 교수가 우리에게하는 일은 그의 도서관을 사용하는 것과 관련이 있습니다. =

.data 
Intro: 
    .ascii "Hey enter in your what you want converted.\n\0" 
Task: 
    .space 5 #This is the buffer that is supposed to limit what the user can enter.... I'm very confused about how to make this work 

.text 
.global _start 

_start: 

    mov $Intro, %rax 
    call PrintCString #from the Prof's library 
    mov $Task, %rbx 
    call ScanCString 

여기 그가 ScanCString 입력 = RAX, RBX 노트를 사용하는 방법에 대한 말씀의 주소 %의 RAX에 널 종료 문자열을 저장합니다를 검사 : 사용자의 입력을 얻기 위해 코드는 다음과 같습니다. 레지스터 % rbx에는 읽을 수있는 최대 문자 수 (버퍼 크기)가 포함되어야합니다.

여기에서 내 생각은 각 캐릭터를 이동하고 대문자인지 소문자인지 결정한 다음 그에 따라 조정할 수 있습니다. 루프를 통해이를 실행하고 사용자에게 다시 알려줍니다.

내가 지금까지 가지고있는 모든 것, 제 시험 물건의 광기에 신경 쓰지 마십시오. 어떤 도움이라도 대단히 감사하겠습니다.

.data 
    Intro: 
     .ascii "\nYup... Mr. Meekseeks here to help. What ya want me to do?\n\n\0" 
    Task: 
     .space 5 
    NewLine: 
     .ascii "\n\n\0" 
    Goodbye: 
     .ascii "\nYou got it buddy I'll get right on doing \0" 
    Test: 
     .ascii "\nYou made it to the first loop\n\0" 
    Test2: 
     .ascii "\nYou made it past the first compare\n\0" 
    Test3: 
     .ascii "\nYou added 1 to the pointer\n\0" 
    Test4: 
     .ascii "\nHere's the string length \0" 

.text 

.global _start 

_start: 

    mov $Intro, %rax    #start with greeting the user 
    call PrintCString    #Print the greeting to the user 
    mov $0, %rax 
    mov Task(,8), %rbx    #move the buffer into RBX, prep for input 
    call ScanCString    #User Input 
# mov %rax, Task 
# mov %rax, %rdx     #Move the message so it's not destroyed 
    call LengthCString    #Determine loop limit 
    mov $0, %rdi     #set pointer 
    mov %rax, %rcx     #set counter to zero 
    mov Task(%rdi), %rax 

    call PrintCString 

    mov $Test4, %rax 
    call PrintCString 
    mov %rcx, %rax 
    call PrintInt 
    mov %rax, %rcx 
    mov $Test, %rax 
    call Loop 

Loop: 
    mov $Test2, %rax 
    call PrintCString 
    add $1, %rdi 
    mov $Test3, %rax 
    call PrintCString 
    cmp %rdi, %rcx 
    je Closing 
    call Loop 

# movb %rax, %rdx 
# mov %rcx, %rax 
# call PrintInt 
# call PrintCString 

# call Ending 

#Adding: 

# Greeting: 

# mov $Intro, %rax 
# call PrintCString 
# ret 

Closing: 
    mov $Goodbye, %rax 
    call PrintCString 

    call Ending 

Ending: 

    mov $NewLine, %rax 
    call PrintCString 
    call EndProgram 

답변

0

ScanCString 입력 = RAX, RBX 노트 = 어드레스 %의 RAX로 널 종료 문자열 저장을 스캔. 레지스터 % rbx에는 읽을 수있는 최대 문자 수 (버퍼 크기)가 포함되어야합니다.

mov $Task, %rax # set rax to point to the buffer in memory 
    mov $5, %rbx  # size of buffer (5 bytes) 
    call ScanCString 

너의 :

mov $0, %rax 

설정 rax가 참조 할 수 있도록합니다 (ScanCString는 "메모리 포인터로 사용합니다 제로

는 다음과 같이 호출해야처럼 보인다 널 포인터 "에 대한 안전성 테스트가있는 경우 충돌을 일으키거나 일찍 종료합니다.

mov Task(,8), %rbx    #move the buffer into RBX, prep for input 

로드 구문 오류, 내가 (,8) 구문 분석하지 않습니다 생각하지만, 나는 그것이 Task(<noreg>,<noreg>,8)처럼 생각한다면 난 아직도 ... & T 구문 전문가 AT 아니에요 같은 사실 가능성이 메모리 주소 Task (에서 8 바이트 인덱스 인자가 없으므로 스케일 팩터 8을 제공하는 것은 의미가 없으므로 논리적으로는 0 오프셋, 작업 주소에 추가, 8 바이트로드에이를 사용합니다.Task:.space 5 뒤에 같이

, 그것은 5 정의 바이트 그 공간 예약로부터 판독된다는 것을 의미하고, 그 후, 다음 3 바이트는 8 바이트 (rbx 크기) 전체 칠 판독한다. (가 3 바이트 이후를 덮어하므로 5 바이트가 예약된다)

call ScanCString    #User Input 
# mov %rax, Task 

이 메모리에 rax 값 8 바이트를 저장할는 Task: 가리키는.

# mov %rax, %rdx     #Move the message so it's not destroyed 

rdx = rax ... 그것은 rax에서 ScanCString 수익을 무엇을, 명확하지, 그래서 사람들은 위의 두 명령에 의해 메모리/RDX에 저장됩니다 것을 알고있다.

call LengthCString    #Determine loop limit 

이 사람은 아마 그래서 mov $Task, %rax가 나에게 논리적 인 것 같다 앞서하고, rax 메모리에 대한 포인터를 기대하고 있지만 LengthCString의 문서를 게시하지 않았다.

... 
jg Subtract 
... 

Subtract: 
    ... 
    ret 

jg는 스택에 저장하지 반환 주소를 수행, 점프, 그래서 마지막에 retcall 해당 ret 필요 당신이 무엇을하고 있는지 알고하지 않으면 당신은 반환 준비 (와 결합 될 수를 잘못 느낀다 주소가 call 이외의 다른 방법으로 스택에 있지만 초보자에게는 그다지 중요하지 않습니다.

Task: 
    .space 5 #This is the buffer that is supposed to limit 
    # what the user can enter.... 
    # I'm very confused about how to make this work 

아니이 단지 코드 (.data)의 현재 구간에서 5 바이트를 보유한다. 그것은 어떤 식 으로든 코드를 제한하지 않으며, 심지어 메모리 내용을 정의하지 않기 때문에 실행시 아무 것도 포함 할 수 있습니다 (대부분 .data은 대부분 0으로 간주되므로 5 개의 0 바이트가 포함될 것입니다). 대부분의 대상 플랫폼에서 (다음 번에는 하나 지정).

5은 소스 코드에 포함되어 있기 때문에 결과 머신 코드의 일부가 아니므로 어셈블러에 알지만 코드 자체는 알지 못합니다. DRY를 원할 경우 buffer_length = 5과 같은 상수를 정의하고 (AT & T 문법에 대해 확실하지 않음) 데이터 섹션 Task: .space buffer_length에서 스캔 호출 mov $buffer_length, %ebx (이면 충분합니다. 4GB 이상은 사용하지 않을 것입니다. 길이를 설정하고 ebx 부분을 설정하면 rbx의 나머지 32 비트가 지워집니다), 마법 상수 5은 소스 코드의 단일 위치에서만 유지됩니다.

전반적으로 레지스터 란 무엇인지, 컴퓨터 메모리는 무엇인지, CPU가 어떻게 상호 작용하는지 등에 대한 전반적인 개념을 놓친 것처럼 보입니다. 설명이 포함 된 책이나 튜토리얼을 읽으십시오. 이미 존재하는 코드를 복사하고 그것을 조정하면 예상 한 결과물을 출력 할 때까지 어셈블리보다는 고급 언어에서 훨씬 잘 작동합니다. 어셈블리에서 더 잘 작동 하는지를 더 잘 이해하려고 노력하십시오. 좋은 점은 컴퓨터가 실제로는 매우 단순한 기계이고 결정적 방식으로 작동하는 상태 - 오토 마톤이며 각 사이클마다 실행될 수있는 명령어가 거의 없기 때문에 이해는 어렵지 않으며 인간을 사용하지 마십시오 그것에 대한 기대/논리, 계산 기계, 인간과 인간이 쓰거나 읽어야하는 고차원 언어가 아닙니다.

또한 어셈블리 코드를 작성할 때 디버거에서 각 명령이 예상대로 작동하는지 확인하고, 한 단계 씩 실행하고, 명령에 의해 생성 된 모든 상태 변경 사항을 확인해야합니다. 불일치가있는 경우에는 지침 참조 안내서를 참조하여 특정 지침이 무엇인지 완전히 이해하는지 확인하십시오. http://www.felixcloutier.com/x86/과 같은 웹에 몇 가지 짧은 버전이 있습니다. 인텔의 원본 pdf (인텔 웹에서 무료로 구할 수 있음)를 파고 들지 않으려는 경우입니다. 악명 높은 예 (및 SO에 대한 질문)는 예를 들어 muldiv이며 일반적인 기대치를 따르지 않습니다.

T 문법은 기계에 의한 구문 분석에 매우 적합한 "기계와 같은"IMO이며, 매우 정밀하고 정확하게하지만 편안한 Intel 구문과 비교할 때 자연스럽게 쓰거나 읽기가 어렵습니다.

특히 같은 것들 :

mov $Task, %rax # set rax to point to the buffer in memory 
mov Task, %rax # set rax to 64b value from memory at Task addres 

기계 구문 분석에 대한 완벽한 이해를 만든다

$는 즉시 값과 메모리 참조 구분하지만, 손으로 $, 당신은 메모리의 주소를 할 때 작성하는 잊지 못할하려고 , 그리고 내용이 아닙니다.