#ios #objective-c #iphone #assembly #arm
#iOS #objective-c #iPhone #сборка #arm
Вопрос:
Я написал функцию сборки, которая отлично работает на iPhone 4 (32-разрядный код), а также на iPhone 6s (64-разрядный код). Я передаю четыре числа с плавающей запятой из вызывающей функции в objective-c.
Вот структура, которую я использую для 4 чисел с плавающей запятой, а ниже приведен прототип функции, который находится в верхней части моего кода objective-c.
struct myValues{ // This is a structure. It is used to conveniently group multiple data items logically.
float A; // I am using it here because i want to return multiple float values from my ASM code
float B; // They get passed in via S0, S1, S2 etc. and they come back out that way too
float number;
float divisor; //gonna be 2.0
}myValues;
struct myValues my_asm(float e, float f, float g, float h); // Prototype for the ASM function
В моем коде objective-c я вызываю свою функцию сборки следующим образом:
myValues = my_asm(myValues.A, myValues.B, myValues.number,myValues.divisor); // ASM function
При запуске на iPhone 6S код выполняется как чемпион (64-разрядный код). 4 значения с плавающей запятой передаются из кода objective-c в код сборки через одиночные регистры с плавающей запятой ARM S0-S4. Возвращаемые результаты также передаются через S0-S4.
При работе с iPhone 4 код также работает нормально (32-разрядный код). 4 значения с плавающей запятой передаются из кода obj-c в код сборки через одиночные регистры с плавающей запятой ARM S0, S2, S4 и S6 (не уверен, почему пропускаются нечетные регистры). Код выполняется нормально, но значения, которые возвращаются в мою структуру obj-c. Это мусор.
Куда / как мне передать значения с плавающей запятой из 32-разрядного кода ARM, чтобы они возвращались в структуру obj-c?
спасибо, relayman357
ps. Ниже приведен мой код сборки из моего файла Xcode S.
.ios_version_min 9, 0
.globl _my_asm
.align 2
#ifdef __arm__
.thumb_func _my_asm
.syntax unified
.code 16
_my_asm: // 32 bit code
// S0 = A, S2 = B, S4 = Number, S6 = 2.0 - parameters passed in when called by the function
vadd.f32 s0, s0, s2
vdiv.f32 s0, s0, s6
vdiv.f32 s1, s4, s0
vcvt.u32.f32 r0,s0
bx lr
//ret
#else
_my_asm: // 64 bit code
//add W0, W0, W1
; S0 = A, S1 = B, S2 = Number, S3 = 2.0 parameters passed in when called by the function
fadd s0, s0, s1
fdiv s0, s0, s3
fdiv s1, s2, s0
ret
#endif
Комментарии:
1. Напишите эквивалентный код на C, а затем разберите его. Где-то там вы не удовлетворяете потребностям ABI.
Ответ №1:
Ни одна из ваших функций не возвращает структуру правильно. Вам нужно понимать ARM ABI. Вы можете начать с чтения руководства Apple по вызову функций iOS ABI. Если после изучения ABI вы не понимаете, задайте новый вопрос, показывающий, что вы пробовали.
HTH
Комментарии:
1. ОБНОВЛЕНИЕ: Хорошо, я думаю, что HTH навел меня на правильный след — я просто еще не совсем там. Ниже приведено то, что мне удалось узнать, начиная с чтения руководства по вызову функций iOS ABI. Теперь я могу получить доступ ко всем параметрам, переданным в код asm, из кода asm. НО я все еще не могу успешно получить значения из моего asm-кода обратно в свою структуру.
2. Я изменил свою структуру «myValues» на 6 поплавков. Первые 3 значения с плавающей запятой передаются в функцию сборки через регистры r1, r2 и r3. Это 32-разрядные регистры, а значения кодируются в формате IEEE 754 с одной плавающей запятой (в отладчике Xcode вы можете щелкнуть правой кнопкой мыши по регистру и выбрать «просмотреть значение как» и выбрать значение с плавающей запятой. Оставшиеся 3 значения с плавающей запятой, которые передаются из вызывающего кода, помещаются в стек и готовы к захвату с помощью следующего кода в функции сборки:
3. Ключи: 1) Распознает, что значения с плавающей запятой хранятся в 32-разрядных общих регистрах (r1-r3) в IEEE 754 Single. 2) При отладке вы можете просмотреть общие регистры и щелкнуть правой кнопкой мыши по «sp» и выбрать «просмотреть память sp», затем вам нужно изменить просмотренную память (по какой-то причине она не переходит на адрес памяти в sp) на фактическую ячейку памяти, хранящуюся в sp.3) Как только вы посмотрите на правильный адрес: 3a) sp указывает на последнее переданное значение. 3b) Значения хранятся в конце строки — например, «00 20 00 40» на самом деле «40 00 20 00» — это число с плавающей запятой 2.002
4. // Добавьте сюда код Prolog, чтобы воспроизвести хорошие vmov s1, r1 // поместите 1-е число с плавающей запятой в кодировке IEEE 754 в S1 vmov s2, r2 // возьмите 2-е число с плавающей запятой и вставьте S2vmov s3, r3 vldr s6, [sp] vldr s5, [sp, # 4] // загрузите 5-е число с плавающей запятойв S5 (333.0) vldr s4, [sp, # 8] // загрузите 4-й поплавок в S4 (444.0) vdiv.f32 s3, s0, s0 // результат S3 = 1.0 Измените значения vadd.f32 s0, s5, s3 // 334.0 vadd.f32 s1, s1, s1// 4.2 vadd.f32 s2, s2, s1 // 9.438 vstr s0, [sp] vstr s1, [sp, # 4] vstr s2, [sp, # 8] // Добавьте сюда код эпилога, чтобы играть красиво
5. Это трудно понять, но я думаю, что вы все еще не можете ответить на очевидный вопрос: как функция может возвращать значение структуры, которое больше, чем поместится в регистре? Теперь есть более одного возможного ответа на этот вопрос, можете ли вы придумать какой-нибудь? Каждый ABI делает свой собственный выбор, если вы не можете найти его в документах, решите это по-другому: напишите свою функцию в Obj-C и разберите ее в Xcode и посмотрите, как она возвращает значение.