AMcoder - javascript, python, java, html, php, sql

օգտագործելով printf-ը օղակի x86-64 հավաքից առաջ և ներսում

Ես դժվարանում եմ պարզել, թե ինչպես ճիշտ օգտագործել printf-ն այս գործառույթում: Այսպիսով, ֆունկցիան կոչվում է multInts և պետք է բազմապատկի առաջին զանգվածի առաջին տարրը երկրորդ զանգվածի առաջին տարրով և շարունակի ամբողջ զանգվածով։ Այնուամենայնիվ, լաբորատորիայի հրահանգները նշում են, որ ես չեմ կարող printf-ը զանգահարել հիմնական գործառույթում: Այսպիսով, ես պետք է տպեմ «Products:\n» բառը և դրանից հետո յուրաքանչյուր նոր տողում տպեմ արտադրանքը: Այնուամենայնիվ, ես չգիտեմ, թե ինչպես օգտագործել printf-ը օղակում: Հրահանգիչն ասաց, որ մենք պետք է «արտադրանքը հաշվարկելուց հետո զանգահարենք printf-ը ցիկլում», ինչպես նաև «պահենք և վերականգնենք զանգահարողների պահպանման գրանցամատյանները՝ նախքան printf-ը զանգահարելը», բայց ես վստահ չեմ, թե դա ինչ է նշանակում: Ահա թե ինչ տեսք ունի իմ կոդը մինչ այժմ.

.file   "lab4.s"
.section .rodata

.LC0:
    .string "Products: \n"
.LC1: 
    .string "%i \n"
.data
sizeIntArrays:
    .long 5
sizeShortArrays:
    .word 4
intArray1:
    .long 10
    .long 25
    .long 33
    .long 48
    .long 52
intArray2:
    .long 20
    .long -37
    .long 42
    .long -61
    .long -10

##### MAIN FUNCTION
.text
.globl main
.type main,@function

main:
pushq %rbp
movq %rsp, %rbp

#pass parameters and call other functions
movl sizeIntArrays, %edi    #move size to registers for 1st parameter
leaq intArray1, %rsi        #load effective address of intArray1 to register rsi
leaq intArray2, %rdx        #load effective address of intArray2 to register rdx
call multInts           #call multInts function

movq $0, %rax           #return 0 to caller

movq %rbp, %rsp
popq %rbp
ret
.size main,.-main


##### MULTINTS
.globl multInts
.type multInts,@function

multInts:
pushq %rbp
movq %rsp, %rbp

#add code here for what the functions should do
movq $0, %r8            #initialize index for array access in caller save reg
movq $0, %rcx           #initialize 8 byte caller save result reg

loop0:
cmpl %r8d, %edi         #compare index to size
je exit0            #exit if equal
movslq (%rsi,%r8,4),%rax    # Load a long into RAX
movslq (%rdx,%r8,4),%r11    # Load a long into R11
imulq %r11, %rax            # RAX *= R11
addq %rax, %rcx             # RCX += RAX
incq %r8            #increment index
jmp loop0

exit0:
movq $.LC0, %rdi
movq %rcx, %rsi
movq $0, %rax

call printf

movq %rbp, %rsp
popq %rbp
ret
.size multInts,.-multInts

Այն, ինչ ես փորձել եմ անել, պարզապես printf հրահանգը տեղափոխել է հանգույցից առաջ, բայց դա ինձ տալիս է սեգմենտավորման սխալ հանգույցը գործարկելիս, քանի որ %rdi և %rsi պարունակում են զանգվածների հասցեները, որոնք պետք է օգտագործվեն ցանցում: հանգույց. Ինչպե՞ս կարող եմ շրջանցել դա և ո՞ր գրանցամատյանները պետք է օգտագործեմ: Բացի այդ, ինչպե՞ս կարող եմ զանգահարել printf-ին օղակի ներսում:

Արդյունքը պետք է նման լինի հետևյալին.

Products:
200
-925
1386
-2928
-520

Պատասխանները:


1

Ռեգիստրը ենթածրագրի մուտքից պաշտպանելու ամենահեշտ ձևը push այն է: Համաձայն ABI V զանգերի կոնվենցիայի printf-ը կարող է փոխել ցանկացած գրանցամատյան, բացառությամբ RBX, RBP, R12–R15 . Այն գրանցամատյանները, որոնք դուք պետք է պահպանեք, հետևյալն են՝ RAX, RDX, RSI, RDI, R8 և R11 (RCX-ն այլևս անհրաժեշտ չէ), այնպես որ push նախքան printf զանգը և pop դրանք հետո.

pushq %rax
pushq %rdx
pushq %rsi
pushq %rdi
pushq %r8
pushq %r11
movq $.LC1, %rdi
movq %rax, %rsi
movq $0, %rax
call printf
popq %r11
popq %r8
popq %rdi
popq %rsi
popq %rdx
popq %rax

Այժմ դուք կարող եք պատճենել բլոկը հանգույցի մեջ: Յուրաքանչյուր տպագրության համար դուք պետք է մտածեք այն մասին, թե ինչ պետք է ապահովվի.

...
multInts:
pushq %rbp
movq %rsp, %rbp

#add code here for what the functions should do

pushq %rdx                  # Preserve registers
pushq %rdi
pushq %rsi
movq $.LC0, %rdi            # Format string (no further values)
movq $0, %rax               # No vector registers used
call printf                 # Call C function
popq %rsi                   # Restore registers
popq %rdi
popq %rdx

movq $0, %r8                #initialize index for array access in caller save reg

loop0:
cmpl %r8d, %edi             #compare index to size
je exit0                    #exit if equal

movslq (%rsi,%r8,4),%rax    # Load a long into RAX
movslq (%rdx,%r8,4),%r11    # Load a long into R11
imulq %r11, %rax            # RAX *= R11

pushq %rax                  # Preserve registers
pushq %rdx
pushq %rsi
pushq %rdi
pushq %r8
pushq %r11
movq $.LC1, %rdi            # Format string
movq %rax, %rsi             # Value
movq $0, %rax               # No vector registers used
call printf                 # Call C function
popq %r11                   # Restore registers
popq %r8
popq %rdi
popq %rsi
popq %rdx
popq %rax

incq %r8                    #increment index
jmp loop0

exit0:

movq %rbp, %rsp
popq %rbp
ret
...

BTW՝ .string "%i \n"-ը կստիպի printf-ին մշակել RDI-ի ստորին 32-բիթանոցը: Փոխարենը օգտագործեք .string %lli \n:

26.11.2018
  • Յուրաքանչյուր printf զանգի շուրջ ամեն ինչի սեղմում/փոփոխությունը սարսափելի է: Ես փնտրում էի, թե ինչպես զանգահարել printf հղումը, և սա հայտնվեց: Դա հակառակն է, ինչ ես խորհուրդ կտայի երբևէ որևէ մեկին անել: (Պարզվում է, որ ես արդեն պատասխանել եմ այս հարցին այն ժամանակ, խորհուրդ տալով օգտագործել զանգերի պահպանված գրանցամատյանները մնացած օղակի համար): 30.10.2019

  • 2

    Ենթադրենք, որ printf-ը խաթարում է բոլոր զանգերի հետ կապված ռեգիստրները (Ինչ ռեգիստրներ են պահպանվում linux x86-64 ֆունկցիայի կանչի միջոցով), և օգտագործեք տարբեր մեկը ամեն ինչի համար, որը պետք է գոյատևի օղակի մի կրկնությունից մյուսը:

    Օրինակի համար նայեք կոմպիլյատորի ելքին. գրեք ձեր հանգույցի տարբերակը C-ով և կազմեք այն -Og-ով:

    Ակնհայտ է, որ դուք պետք է call printf-ի հետ միասին տեղափոխեք այն հրահանգները, որոնք կարգավորում են args-ը գրանցամատյաններում (ինչպես ձևաչափի տողը):

    26.11.2018
    Նոր նյութեր

    Օգտագործելով Fetch Vs Axios.Js-ը՝ HTTP հարցումներ կատարելու համար
    JavaScript-ը կարող է ցանցային հարցումներ ուղարկել սերվեր և բեռնել նոր տեղեկատվություն, երբ դա անհրաժեշտ լինի: Օրինակ, մենք կարող ենք օգտագործել ցանցային հարցումը պատվեր ներկայացնելու,..

    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար
    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար Ինչպե՞ս հանգստացնել ձեր միտքը և աշխատեցնել ձեր պրոցեսորը: Ինչպես մնալ հանգիստ և զարգանալ ճնշման տակ...

    Մեքենայի ուսուցում բանկային և ֆինանսների ոլորտում
    Բարդ, խելացի անվտանգության համակարգերը և հաճախորդների սպասարկման պարզեցված ծառայությունները բիզնեսի հաջողության բանալին են: Ֆինանսական հաստատությունները, մասնավորապես, պետք է առաջ մնան կորի..

    Ես AI-ին հարցրի կյանքի իմաստը, այն ինչ ասում էր, ցնցող էր:
    Այն պահից ի վեր, երբ ես իմացա Արհեստական ​​ինտելեկտի մասին, ես հիացած էի այն բանով, թե ինչպես է այն կարողանում հասկանալ մարդկային նորմալ տեքստը, և այն կարող է առաջացնել իր սեփական արձագանքը դրա..

    Ինչպես սովորել կոդավորումը Python-ում վագրի պես:
    Սովորելու համար ծրագրավորման նոր լեզու ընտրելը բարդ է: Անկախ նրանից, թե դուք սկսնակ եք, թե առաջադեմ, դա օգնում է իմանալ, թե ինչ թեմաներ պետք է սովորել: Ծրագրավորման լեզվի հիմունքները, դրա..

    C++-ի օրական բիթ(ե) | Ամենաերկար պալինդրոմային ենթաշարը
    C++ #198-ի ամենօրյա բիթ(ե), Ընդհանուր հարցազրույցի խնդիր. Ամենաերկար պալինդրոմային ենթատող: Այսօր մենք կանդրադառնանք հարցազրույցի ընդհանուր խնդրին. Ամենաերկար palindromic substring...

    Kydavra ICAReducer՝ ձեր տվյալների ծավալայինությունը նվազեցնելու համար
    Ի՞նչ է ICAReducer-ը: ICAReducer-ն աշխատում է հետևյալ կերպ. այն նվազեցնում է նրանց միջև բարձր փոխկապակցված հատկանիշները մինչև մեկ սյունակ: Բավականին նման է PCAreducer-ին, չնայած այն..